Extensions.java

1
package com.yubico.webauthn.data;
2
3
import com.fasterxml.jackson.annotation.JsonCreator;
4
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5
import com.fasterxml.jackson.annotation.JsonProperty;
6
import com.fasterxml.jackson.annotation.JsonValue;
7
import com.upokecenter.cbor.CBORObject;
8
import com.upokecenter.cbor.CBORType;
9
import com.yubico.internal.util.ExceptionUtil;
10
import com.yubico.webauthn.FinishRegistrationOptions;
11
import com.yubico.webauthn.RelyingParty;
12
import com.yubico.webauthn.StartAssertionOptions;
13
import com.yubico.webauthn.StartRegistrationOptions;
14
import com.yubico.webauthn.extension.uvm.KeyProtectionType;
15
import com.yubico.webauthn.extension.uvm.MatcherProtectionType;
16
import com.yubico.webauthn.extension.uvm.UserVerificationMethod;
17
import java.util.Arrays;
18
import java.util.Collections;
19
import java.util.HashMap;
20
import java.util.List;
21
import java.util.Map;
22
import java.util.Optional;
23
import java.util.Set;
24
import java.util.stream.Collectors;
25
import java.util.stream.Stream;
26
import lombok.AllArgsConstructor;
27
import lombok.Builder;
28
import lombok.NonNull;
29
import lombok.Value;
30
import lombok.experimental.UtilityClass;
31
import lombok.extern.slf4j.Slf4j;
32
33
/** Definitions for WebAuthn extensions. */
34
@Slf4j
35
@UtilityClass
36
public class Extensions {
37
38
  /**
39
   * Definitions for the FIDO AppID Extension (<code>appid</code>).
40
   *
41
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-extension">§10.1.
42
   *     FIDO AppID Extension (appid)</a>
43
   */
44
  public static class Appid {
45
    static final String EXTENSION_ID = "appid";
46
  }
47
48
  /**
49
   * Definitions for the 10.2. FIDO AppID Exclusion Extension (<code>appidExclude</code>).
50
   *
51
   * @see <a
52
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-exclude-extension">10.2.
53
   *     FIDO AppID Exclusion Extension (appidExclude)</a>
54
   */
55
  public static class AppidExclude {
56
    static final String EXTENSION_ID = "appidExclude";
57
  }
58
59
  /**
60
   * Definitions for the Credential Properties Extension (<code>credProps</code>).
61
   *
62
   * @see <a
63
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-authenticator-credential-properties-extension">§10.4.
64
   *     Credential Properties Extension (credProps)</a>
65
   */
66
  public static class CredentialProperties {
67
    static final String EXTENSION_ID = "credProps";
68
69
    /**
70
     * Extension outputs for the Credential Properties Extension (<code>credProps</code>).
71
     *
72
     * @see <a
73
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-authenticator-credential-properties-extension">§10.4.
74
     *     Credential Properties Extension (credProps)</a>
75
     */
76
    @Value
77
    @Builder
78
    @JsonIgnoreProperties(ignoreUnknown = true)
79
    public static class CredentialPropertiesOutput {
80
      @JsonProperty("rk")
81
      private final Boolean rk;
82
83
      @JsonCreator
84
      private CredentialPropertiesOutput(@JsonProperty("rk") Boolean rk) {
85
        this.rk = rk;
86
      }
87
88
      /**
89
       * This OPTIONAL property, known abstractly as the <b>resident key credential property</b>
90
       * (i.e., <b>client-side discoverable credential property</b>), is a Boolean value indicating
91
       * whether the {@link PublicKeyCredential} returned as a result of a registration ceremony is
92
       * a <i>client-side discoverable credential</i> (passkey).
93
       *
94
       * <p>If this is <code>true</code>, the credential is a <i>discoverable credential</i>
95
       * (passkey).
96
       *
97
       * <p>If this is <code>false</code>, the credential is a <i>server-side credential</i>.
98
       *
99
       * <p>If this is not present, it is not known whether the credential is a discoverable
100
       * credential or a server-side credential.
101
       *
102
       * @see <a
103
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-credentialpropertiesoutput-rk">§10.4.
104
       *     Credential Properties Extension (credProps)</a>
105
       * @see <a
106
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#client-side-discoverable-credential">Client-side
107
       *     discoverable Credential</a>
108
       * @see <a
109
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#server-side-credential">Server-side
110
       *     Credential</a>
111
       * @see <a href="https://passkeys.dev/docs/reference/terms/#passkey">Passkey</a> in <a
112
       *     href="https://passkeys.dev">passkeys.dev</a> reference
113
       */
114
      public Optional<Boolean> getRk() {
115 1 1. getRk : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProperties$CredentialPropertiesOutput::getRk → KILLED
        return Optional.ofNullable(rk);
116
      }
117
    }
118
  }
119
120
  /**
121
   * Definitions for the Credential Protection (<code>credProtect</code>) extension.
122
   *
123
   * @since 2.7.0
124
   * @see <a
125
   *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
126
   *     §12.1. Credential Protection (credProtect)</a>
127
   */
128
  public static class CredentialProtection {
129
    static final String EXTENSION_ID = "credProtect";
130
131
    /**
132
     * Policy values for the Credential Protection (<code>credProtect</code>) extension.
133
     *
134
     * <p>Available values:
135
     *
136
     * <ul>
137
     *   <li>{@link #UV_OPTIONAL}
138
     *   <li>{@link #UV_OPTIONAL_WITH_CREDENTIAL_ID_LIST}
139
     *   <li>{@link #UV_REQUIRED}
140
     * </ul>
141
     *
142
     * @since 2.7.0
143
     * @see <a
144
     *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
145
     *     §12.1. Credential Protection (credProtect)</a>
146
     * @see CredentialProtectionInput#prefer(CredentialProtectionPolicy)
147
     * @see CredentialProtectionInput#require(CredentialProtectionPolicy)
148
     */
149
    @AllArgsConstructor
150
    public enum CredentialProtectionPolicy {
151
      /**
152
       * In this configuration, performing some form of user verification is always OPTIONAL. This
153
       * is the default behaviour if the extension is not specified; note however that some browsers
154
       * may set a different default extension input if the extension is not explicitly specified.
155
       *
156
       * @since 2.7.0
157
       * @see <a
158
       *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
159
       *     §12.1. Credential Protection (credProtect)</a>
160
       * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#user-verification">User
161
       *     Verification</a>
162
       */
163
      UV_OPTIONAL(0x01, "userVerificationOptional"),
164
165
      /**
166
       * In this configuration, performing some form of user verification is OPTIONAL when the
167
       * credential is used as the second authentication factor, and REQUIRED when the credential is
168
       * used as the first authentication factor.
169
       *
170
       * <p>In technical terms, user verification is REQUIRED when {@link
171
       * PublicKeyCredentialRequestOptions#getAllowCredentials() allowCredentials} is empty and
172
       * OPTIONAL when it is non-empty. {@link
173
       * PublicKeyCredentialRequestOptions#getAllowCredentials() allowCredentials} is non-empty when
174
       * {@link StartAssertionOptions.StartAssertionOptionsBuilder#username(String) username} or
175
       * {@link StartAssertionOptions.StartAssertionOptionsBuilder#userHandle(ByteArray) userHandle}
176
       * was set in the call to {@link RelyingParty#startAssertion(StartAssertionOptions)}, and is
177
       * empty when neither was set.
178
       *
179
       * @since 2.7.0
180
       * @see <a
181
       *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
182
       *     §12.1. Credential Protection (credProtect)</a>
183
       * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#user-verification">User
184
       *     Verification</a>
185
       */
186
      UV_OPTIONAL_WITH_CREDENTIAL_ID_LIST(0x02, "userVerificationOptionalWithCredentialIDList"),
187
188
      /**
189
       * In this configuration, performing some form of user verification is always REQUIRED.
190
       *
191
       * @since 2.7.0
192
       * @see <a
193
       *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
194
       *     §12.1. Credential Protection (credProtect)</a>
195
       * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#user-verification">User
196
       *     Verification</a>
197
       */
198
      UV_REQUIRED(0x03, "userVerificationRequired");
199
200
      final int cborValue;
201
202
      @JsonValue private final String jsValue;
203
204
      private static Optional<CredentialProtectionPolicy> fromCbor(int cborValue) {
205 1 1. fromCbor : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::fromCbor → KILLED
        return Arrays.stream(CredentialProtectionPolicy.values())
206 2 1. lambda$fromCbor$0 : replaced boolean return with true for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromCbor$0 → KILLED
2. lambda$fromCbor$0 : negated conditional → KILLED
            .filter(policy -> policy.cborValue == cborValue)
207
            .findAny();
208
      }
209
210
      private static Optional<CredentialProtectionPolicy> fromJs(String jsonValue) {
211 1 1. fromJs : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::fromJs → KILLED
        return Arrays.stream(CredentialProtectionPolicy.values())
212 2 1. lambda$fromJs$1 : replaced boolean return with false for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromJs$1 → KILLED
2. lambda$fromJs$1 : replaced boolean return with true for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromJs$1 → KILLED
            .filter(policy -> policy.jsValue.equals(jsonValue))
213
            .findAny();
214
      }
215
216
      @JsonCreator
217 1 1. fromJsonString : negated conditional → KILLED
      private static CredentialProtectionPolicy fromJsonString(@NonNull String value) {
218 1 1. fromJsonString : replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::fromJsonString → KILLED
        return fromJs(value)
219
            .orElseThrow(
220
                () ->
221 1 1. lambda$fromJsonString$2 : replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromJsonString$2 → NO_COVERAGE
                    new IllegalArgumentException(
222
                        String.format(
223
                            "Unknown %s value: %s",
224
                            CredentialProtectionPolicy.class.getSimpleName(), value)));
225
      }
226
    }
227
228
    /**
229
     * Extension inputs for the Credential Protection (<code>credProtect</code>) extension.
230
     *
231
     * <p>Instances may be created using the {@link #prefer(CredentialProtectionPolicy)} and {@link
232
     * #require(CredentialProtectionPolicy)} factory functions.
233
     *
234
     * @since 2.7.0
235
     * @see <a
236
     *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
237
     *     §12.1. Credential Protection (credProtect)</a>
238
     */
239
    @Value
240
    public static class CredentialProtectionInput {
241
      /**
242
       * The requested credential protection policy. This policy may or may not be satisfied; see
243
       * {@link #isEnforceCredentialProtectionPolicy()}.
244
       *
245
       * @since 2.7.0
246
       * @see CredentialProtectionPolicy
247
       * @see #isEnforceCredentialProtectionPolicy()
248
       * @see <a
249
       *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
250
       *     §12.1. Credential Protection (credProtect)</a>
251
       */
252
      private final CredentialProtectionPolicy credentialProtectionPolicy;
253
254
      /**
255
       * If this is <code>true</code> and {@link #getCredentialProtectionPolicy()
256
       * credentialProtectionPolicy} is not {@link CredentialProtectionPolicy#UV_OPTIONAL}, {@link
257
       * RelyingParty#finishRegistration(FinishRegistrationOptions)} will validate that the policy
258
       * set in {@link #getCredentialProtectionPolicy()} was satisfied and the browser is requested
259
       * to fail the registration if the policy cannot be satisfied.
260
       *
261
       * <p>{@link CredentialProtectionInput#prefer(CredentialProtectionPolicy)} sets this to <code>
262
       * false</code>. {@link CredentialProtectionInput#require(CredentialProtectionPolicy)} sets
263
       * this to <code>true</code>.
264
       *
265
       * @since 2.7.0
266
       * @see CredentialProtectionPolicy
267
       * @see #getCredentialProtectionPolicy()
268
       * @see <a
269
       *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
270
       *     §12.1. Credential Protection (credProtect)</a>
271
       */
272
      private final boolean enforceCredentialProtectionPolicy;
273
274
      @JsonCreator
275
      private CredentialProtectionInput(
276
          @JsonProperty("credentialProtectionPolicy")
277
              CredentialProtectionPolicy credentialProtectionPolicy,
278
          @JsonProperty("enforceCredentialProtectionPolicy")
279
              Boolean enforceCredentialProtectionPolicy) {
280
        this.credentialProtectionPolicy = credentialProtectionPolicy;
281 1 1. <init> : negated conditional → KILLED
        this.enforceCredentialProtectionPolicy =
282 1 1. <init> : negated conditional → KILLED
            enforceCredentialProtectionPolicy != null && enforceCredentialProtectionPolicy;
283
      }
284
285
      /**
286
       * Create a Credential Protection (<code>credProtect</code>) extension input that requests the
287
       * given policy when possible.
288
       *
289
       * <p>If the policy cannot be satisfied, the browser is requested to continue the registration
290
       * anyway. To determine what policy was applied, use {@link
291
       * AuthenticatorRegistrationExtensionOutputs#getCredProtect()} to inspect the extension
292
       * output. {@link RelyingParty#finishRegistration(FinishRegistrationOptions)} will not
293
       * validate what policy was applied.
294
       *
295
       * <p>Use {@link #require(CredentialProtectionPolicy)} instead to forbid the registration from
296
       * proceeding if the extension is not supported or the policy cannot be satisfied.
297
       *
298
       * @param policy the policy to request.
299
       * @return a <code>credProtect</code> extension input that requests the given policy when
300
       *     possible. The browser is requested to continue the registration even if this policy
301
       *     cannot be satisfied.
302
       * @since 2.7.0
303
       * @see #require(CredentialProtectionPolicy)
304
       * @see <a
305
       *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
306
       *     §12.1. Credential Protection (credProtect)</a>
307
       */
308
      public static CredentialProtectionInput prefer(
309 1 1. prefer : negated conditional → KILLED
          @NonNull final CredentialProtectionPolicy policy) {
310 1 1. prefer : replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionInput::prefer → KILLED
        return new CredentialProtectionInput(policy, false);
311
      }
312
313
      /**
314
       * Create a Credential Protection (<code>credProtect</code>) extension input that requires the
315
       * given policy.
316
       *
317
       * <p>If the policy is not {@link CredentialProtectionPolicy#UV_OPTIONAL} and cannot be
318
       * satisfied, the browser is requested to abort the registration instead of proceeding. {@link
319
       * RelyingParty#finishRegistration(FinishRegistrationOptions)} will validate that the policy
320
       * returned in the authenticator extension output equals this input policy, and throw an
321
       * exception otherwise. You can also use {@link
322
       * AuthenticatorRegistrationExtensionOutputs#getCredProtect()} to inspect the extension output
323
       * yourself.
324
       *
325
       * <p>Note that if the browser or authenticator does not support the extension, the
326
       * registration will fail. Use {@link #prefer(CredentialProtectionPolicy)} instead to allow
327
       * the registration to proceed if the extension is not supported or the policy cannot be
328
       * satisfied.
329
       *
330
       * @param policy the policy to require.
331
       * @return a <code>credProtect</code> extension input that requires the given policy. The
332
       *     browser is requested to abort the registration if this policy cannot be satisfied.
333
       * @since 2.7.0
334
       * @see <a
335
       *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
336
       *     §12.1. Credential Protection (credProtect)</a>
337
       */
338
      public static CredentialProtectionInput require(
339 1 1. require : negated conditional → KILLED
          @NonNull final CredentialProtectionPolicy policy) {
340 1 1. require : replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionInput::require → KILLED
        return new CredentialProtectionInput(policy, true);
341
      }
342
    }
343
344
    /**
345
     * Validate that the given response satisfies the <code>credProtect</code> extension policy set
346
     * in the request.
347
     *
348
     * <p>If the {@link
349
     * RegistrationExtensionInputs.RegistrationExtensionInputsBuilder#credProtect(CredentialProtectionInput)
350
     * credProtect} extension is not set in the request, this has no effect.
351
     *
352
     * <p>If the {@link
353
     * RegistrationExtensionInputs.RegistrationExtensionInputsBuilder#credProtect(CredentialProtectionInput)
354
     * credProtect} extension is set in the request with {@link
355
     * CredentialProtectionInput#isEnforceCredentialProtectionPolicy()
356
     * enforceCredentialProtectionPolicy} set to <code>false</code> or {@link
357
     * CredentialProtectionInput#getCredentialProtectionPolicy() credentialProtectionPolicy} set to
358
     * {@link CredentialProtectionPolicy#UV_OPTIONAL}, this has no effect.
359
     *
360
     * <p>If the {@link
361
     * RegistrationExtensionInputs.RegistrationExtensionInputsBuilder#credProtect(CredentialProtectionInput)
362
     * credProtect} extension is set in the request with {@link
363
     * CredentialProtectionInput#isEnforceCredentialProtectionPolicy()
364
     * enforceCredentialProtectionPolicy} set to <code>true</code> and {@link
365
     * CredentialProtectionInput#getCredentialProtectionPolicy() credentialProtectionPolicy} is not
366
     * set to {@link CredentialProtectionPolicy#UV_OPTIONAL}, then this throws an {@link
367
     * IllegalArgumentException} if the <code>credProtect</code> authenticator extension output does
368
     * not equal the {@link CredentialProtectionInput#getCredentialProtectionPolicy()
369
     * credentialProtectionPolicy} set in the request.
370
     *
371
     * <p>This function is called automatically in {@link
372
     * RelyingParty#finishRegistration(FinishRegistrationOptions)}; you should not need to call it
373
     * yourself.
374
     *
375
     * @param request the arguments to start the registration ceremony.
376
     * @param response the response from the registration ceremony.
377
     * @throws IllegalArgumentException if the {@link
378
     *     RegistrationExtensionInputs.RegistrationExtensionInputsBuilder#credProtect(CredentialProtectionInput)
379
     *     credProtect} extension is set in the request with {@link
380
     *     CredentialProtectionInput#isEnforceCredentialProtectionPolicy()
381
     *     enforceCredentialProtectionPolicy} set to <code>true</code> and {@link
382
     *     CredentialProtectionInput#getCredentialProtectionPolicy() credentialProtectionPolicy} not
383
     *     set to {@link CredentialProtectionPolicy#UV_OPTIONAL}, and the <code>credProtect
384
     *     </code> authenticator extension output does not equal the {@link
385
     *     CredentialProtectionInput#getCredentialProtectionPolicy() credentialProtectionPolicy} set
386
     *     in the request.
387
     * @since 2.7.0
388
     * @see <a
389
     *     href="https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-credProtect-extension">CTAP2
390
     *     §12.1. Credential Protection (credProtect)</a>
391
     */
392
    public static void validateExtensionOutput(
393
        PublicKeyCredentialCreationOptions request,
394
        PublicKeyCredential<AuthenticatorAttestationResponse, ClientRegistrationExtensionOutputs>
395
            response) {
396
      request
397
          .getExtensions()
398
          .getCredProtect()
399 1 1. validateExtensionOutput : removed call to java/util/Optional::ifPresent → KILLED
          .ifPresent(
400
              credProtectInput -> {
401 1 1. lambda$validateExtensionOutput$0 : negated conditional → KILLED
                if (credProtectInput.isEnforceCredentialProtectionPolicy()
402 1 1. lambda$validateExtensionOutput$0 : negated conditional → KILLED
                    && credProtectInput.getCredentialProtectionPolicy()
403
                        != CredentialProtectionPolicy.UV_OPTIONAL) {
404
                  Optional<CredentialProtectionPolicy> outputPolicy =
405
                      response
406
                          .getResponse()
407
                          .getParsedAuthenticatorData()
408
                          .getExtensions()
409
                          .flatMap(CredentialProtection::parseAuthenticatorExtensionOutput);
410 1 1. lambda$validateExtensionOutput$0 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
                  ExceptionUtil.assertTrue(
411
                      outputPolicy.equals(
412
                          Optional.of(credProtectInput.getCredentialProtectionPolicy())),
413
                      "Unsatisfied credProtect policy: required %s, got: %s",
414
                      credProtectInput.getCredentialProtectionPolicy(),
415
                      outputPolicy);
416
                }
417
              });
418
    }
419
420
    static Optional<CredentialProtectionPolicy> parseAuthenticatorExtensionOutput(CBORObject cbor) {
421 1 1. parseAuthenticatorExtensionOutput : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection::parseAuthenticatorExtensionOutput → KILLED
      return Optional.ofNullable(cbor.get(EXTENSION_ID))
422
          .map(
423
              cborObject ->
424 3 1. lambda$parseAuthenticatorExtensionOutput$1 : replaced Integer return value with 0 for com/yubico/webauthn/data/Extensions$CredentialProtection::lambda$parseAuthenticatorExtensionOutput$1 → KILLED
2. lambda$parseAuthenticatorExtensionOutput$1 : negated conditional → KILLED
3. lambda$parseAuthenticatorExtensionOutput$1 : negated conditional → KILLED
                  cborObject.isNumber() && cborObject.AsNumber().IsInteger()
425
                      ? cborObject.AsInt32()
426
                      : null)
427 1 1. lambda$parseAuthenticatorExtensionOutput$2 : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection::lambda$parseAuthenticatorExtensionOutput$2 → KILLED
          .flatMap(CredentialProtectionPolicy::fromCbor);
428
    }
429
  }
430
431
  /**
432
   * Definitions for the Large blob storage extension (<code>largeBlob</code>).
433
   *
434
   * @see <a
435
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
436
   *     Large blob storage extension (largeBlob)</a>
437
   */
438
  public static class LargeBlob {
439
    static final String EXTENSION_ID = "largeBlob";
440
441
    /**
442
     * Extension inputs for the Large blob storage extension (<code>largeBlob</code>) in
443
     * registration ceremonies.
444
     *
445
     * @see <a
446
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
447
     *     Large blob storage extension (largeBlob)</a>
448
     */
449
    @Value
450
    public static class LargeBlobRegistrationInput {
451
      /**
452
       * The Relying Party's preference of whether the created credential should support the <code>
453
       * largeBlob</code> extension.
454
       */
455
      @JsonProperty private final LargeBlobSupport support;
456
457
      @JsonCreator
458
      public LargeBlobRegistrationInput(
459
          /**
460
           * The Relying Party's preference of whether the created credential should support the
461
           * <code>
462
           * largeBlob</code> extension.
463
           *
464
           * <p>Currently the only valid values are {@link LargeBlobSupport#REQUIRED} and {@link
465
           * LargeBlobSupport#PREFERRED}, but custom values MAY be constructed in case more values
466
           * are added in future revisions of the extension.
467
           */
468
          @JsonProperty("support") LargeBlobSupport support) {
469
        this.support = support;
470
      }
471
472
      /**
473
       * The known valid arguments for the Large blob storage extension (<code>largeBlob</code>)
474
       * input in registration ceremonies.
475
       *
476
       * <p>Currently the only valid values are {@link LargeBlobSupport#REQUIRED} and {@link
477
       * LargeBlobSupport#PREFERRED}, but custom values MAY be constructed in case more values are
478
       * added in future revisions of the extension.
479
       *
480
       * @see #REQUIRED
481
       * @see #PREFERRED
482
       * @see <a
483
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
484
       *     Large blob storage extension (largeBlob)</a>
485
       */
486
      @Value
487
      public static class LargeBlobSupport {
488
        /**
489
         * The authenticator used for registration MUST support the <code>largeBlob</code>
490
         * extension.
491
         *
492
         * <p>Note: If the client does not support the <code>largeBlob</code> extension, this
493
         * requirement MAY be ignored.
494
         *
495
         * <p>Note: CTAP authenticators only support <code>largeBlob</code> in combination with
496
         * {@link AuthenticatorSelectionCriteria#getResidentKey()} set to <code>REQUIRED</code> in
497
         * {@link StartRegistrationOptions#getAuthenticatorSelection()}.
498
         *
499
         * @see <a
500
         *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
501
         *     Large blob storage extension (largeBlob)</a>
502
         */
503
        public static final LargeBlobSupport REQUIRED = new LargeBlobSupport("required");
504
505
        /**
506
         * If the authenticator used for registration supports the <code>largeBlob</code> extension,
507
         * it will be enabled for the created credential. If not supported, the credential will be
508
         * created without large blob support.
509
         *
510
         * <p>Note: CTAP authenticators only support <code>largeBlob</code> in combination with
511
         * {@link AuthenticatorSelectionCriteria#getResidentKey()} set to <code>REQUIRED</code> in
512
         * {@link StartRegistrationOptions#getAuthenticatorSelection()}.
513
         *
514
         * @see <a
515
         *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
516
         *     Large blob storage extension (largeBlob)</a>
517
         */
518
        public static final LargeBlobSupport PREFERRED = new LargeBlobSupport("preferred");
519
520
        /**
521
         * The underlying string value of this {@link LargeBlobSupport} value.
522
         *
523
         * @see #REQUIRED
524
         * @see #PREFERRED
525
         */
526
        @JsonValue private final String value;
527
528
        /**
529
         * Returns a new {@link Set} containing the {@link #REQUIRED} and {@link #PREFERRED} values.
530
         */
531
        public static Set<LargeBlobSupport> values() {
532 1 1. values : replaced return value with Collections.emptySet for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobRegistrationInput$LargeBlobSupport::values → KILLED
          return Stream.of(REQUIRED, PREFERRED).collect(Collectors.toSet());
533
        }
534
      }
535
    }
536
537
    /**
538
     * Extension inputs for the Large blob storage extension (<code>largeBlob</code>) in
539
     * authentication ceremonies.
540
     *
541
     * <p>Use the {@link #read()} and {@link #write(ByteArray)} factory functions to construct this
542
     * type.
543
     *
544
     * @see <a
545
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
546
     *     Large blob storage extension (largeBlob)</a>
547
     */
548
    @Value
549
    public static class LargeBlobAuthenticationInput {
550
      /**
551
       * If <code>true</code>, indicates that the Relying Party would like to fetch the
552
       * previously-written blob associated with the asserted credential.
553
       *
554
       * @see #read()
555
       * @see <a
556
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
557
       *     Large blob storage extension (largeBlob)</a>
558
       */
559
      @JsonProperty private final boolean read;
560
561
      /**
562
       * An opaque byte string that the Relying Party wishes to store with the existing credential.
563
       *
564
       * @see #write(ByteArray)
565
       * @see <a
566
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-write">§10.5.
567
       *     Large blob storage extension (largeBlob)</a>
568
       */
569
      @JsonProperty private final ByteArray write;
570
571
      @JsonCreator
572
      private LargeBlobAuthenticationInput(
573
          @JsonProperty("read") final Boolean read, @JsonProperty("write") final ByteArray write) {
574 3 1. <init> : negated conditional → KILLED
2. <init> : negated conditional → KILLED
3. <init> : negated conditional → KILLED
        if (read != null && read && write != null) {
575
          throw new IllegalArgumentException(
576
              "Parameters \"read\" and \"write\" of largeBlob extension must not both be present.");
577
        }
578
579 2 1. <init> : negated conditional → KILLED
2. <init> : negated conditional → KILLED
        this.read = read != null && read;
580
        this.write = write;
581
      }
582
583
      /**
584
       * Configure the Large blob storage extension (<code>largeBlob</code>) to fetch the
585
       * previously-written blob associated with the asserted credential.
586
       *
587
       * <p>Mutually exclusive with {@link #write(ByteArray)}.
588
       *
589
       * @see <a
590
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
591
       *     Large blob storage extension (largeBlob)</a>
592
       */
593
      public static LargeBlobAuthenticationInput read() {
594 1 1. read : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::read → KILLED
        return new LargeBlobAuthenticationInput(true, null);
595
      }
596
597
      /**
598
       * Configure the Large blob storage extension (<code>largeBlob</code>) to store the given byte
599
       * array with the existing credential.
600
       *
601
       * <p>Mutually exclusive with {@link #read()}.
602
       *
603
       * @see <a
604
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-write">§10.5.
605
       *     Large blob storage extension (largeBlob)</a>
606
       */
607 1 1. write : negated conditional → KILLED
      public static LargeBlobAuthenticationInput write(@NonNull final ByteArray write) {
608 1 1. write : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::write → SURVIVED
        return new LargeBlobAuthenticationInput(false, write);
609
      }
610
611
      /**
612
       * @return <code>true</code> if the <code>read</code> property is set to <code>true</code>,
613
       *     <code>false</code> otherwise.
614
       * @see #read()
615
       * @see <a
616
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
617
       *     Large blob storage extension (largeBlob)</a>
618
       */
619
      public boolean getRead() {
620 2 1. getRead : replaced boolean return with false for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getRead → KILLED
2. getRead : replaced boolean return with true for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getRead → KILLED
        return read;
621
      }
622
623
      /**
624
       * @return The value of the <code>write</code> property if configured, empty otherwise.
625
       * @see #write(ByteArray)
626
       * @see <a
627
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
628
       *     Large blob storage extension (largeBlob)</a>
629
       */
630
      public Optional<ByteArray> getWrite() {
631 1 1. getWrite : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getWrite → SURVIVED
        return Optional.ofNullable(write);
632
      }
633
    }
634
635
    /**
636
     * Extension outputs for the Large blob storage extension (<code>largeBlob</code>) in
637
     * registration ceremonies.
638
     *
639
     * <p>Use the {@link #supported(boolean)} factory function to construct this type.
640
     *
641
     * @see <a
642
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
643
     *     Large blob storage extension (largeBlob)</a>
644
     */
645
    @Value
646
    public static class LargeBlobRegistrationOutput {
647
      /**
648
       * <code>true</code> if, and only if, the created credential supports storing large blobs.
649
       *
650
       * @see <a
651
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargebloboutputs-supported">§10.5.
652
       *     Large blob storage extension (largeBlob)</a>
653
       * @see LargeBlobRegistrationInput#getSupport()
654
       */
655
      @JsonProperty private final boolean supported;
656
657
      @JsonCreator
658
      private LargeBlobRegistrationOutput(@JsonProperty("supported") boolean supported) {
659
        this.supported = supported;
660
      }
661
662
      /**
663
       * Create a Large blob storage extension output with the <code>supported</code> output set to
664
       * the given value.
665
       *
666
       * @see <a
667
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dictdef-authenticationextensionslargebloboutputs">
668
       *     dictionary AuthenticationExtensionsLargeBlobOutputs</a>
669
       */
670
      public static LargeBlobRegistrationOutput supported(boolean supported) {
671 1 1. supported : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobRegistrationOutput::supported → KILLED
        return new LargeBlobRegistrationOutput(supported);
672
      }
673
    }
674
675
    /**
676
     * Extension outputs for the Large blob storage extension (<code>largeBlob</code>) in
677
     * authentication ceremonies.
678
     *
679
     * @see <a
680
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
681
     *     Large blob storage extension (largeBlob)</a>
682
     */
683
    @Value
684
    public static class LargeBlobAuthenticationOutput {
685
      @JsonProperty private final ByteArray blob;
686
      @JsonProperty private final Boolean written;
687
688
      @JsonCreator
689
      private LargeBlobAuthenticationOutput(
690
          @JsonProperty("blob") ByteArray blob, @JsonProperty("written") Boolean written) {
691
        this.blob = blob;
692
        this.written = written;
693
      }
694
695
      /**
696
       * Create a Large blob storage extension output with the <code>blob</code> output set to the
697
       * given value.
698
       *
699
       * <p>This corresponds to the extension input {@link LargeBlobAuthenticationInput#read()
700
       * LargeBlobAuthenticationInput.read()}.
701
       *
702
       * @see <a
703
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dictdef-authenticationextensionslargebloboutputs">
704
       *     dictionary AuthenticationExtensionsLargeBlobOutputs</a>
705
       */
706
      public static LargeBlobAuthenticationOutput read(final ByteArray blob) {
707 1 1. read : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::read → KILLED
        return new LargeBlobAuthenticationOutput(blob, null);
708
      }
709
710
      /**
711
       * Create a Large blob storage extension output with the <code>written</code> output set to
712
       * the given value.
713
       *
714
       * <p>This corresponds to the extension input {@link
715
       * LargeBlobAuthenticationInput#write(ByteArray)
716
       * LargeBlobAuthenticationInput.write(ByteArray)}.
717
       *
718
       * @see <a
719
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dictdef-authenticationextensionslargebloboutputs">
720
       *     dictionary AuthenticationExtensionsLargeBlobOutputs</a>
721
       */
722
      public static LargeBlobAuthenticationOutput write(final boolean write) {
723 1 1. write : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::write → KILLED
        return new LargeBlobAuthenticationOutput(null, write);
724
      }
725
726
      /**
727
       * The opaque byte string that was associated with the credential identified by {@link
728
       * PublicKeyCredential#getId()}. Only valid if {@link LargeBlobAuthenticationInput#getRead()}
729
       * was <code>true</code>.
730
       *
731
       * @return A present {@link Optional} if {@link LargeBlobAuthenticationInput#getRead()} was
732
       *     <code>true</code> and the blob content was successfully read. Otherwise (if {@link
733
       *     LargeBlobAuthenticationInput#getRead()} was <code>false</code> or the content failed to
734
       *     be read) an empty {@link Optional}.
735
       * @see <a
736
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargebloboutputs-blob">§10.5.
737
       *     Large blob storage extension (largeBlob)</a>
738
       */
739
      public Optional<ByteArray> getBlob() {
740 1 1. getBlob : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::getBlob → KILLED
        return Optional.ofNullable(blob);
741
      }
742
743
      /**
744
       * A boolean that indicates that the contents of {@link
745
       * LargeBlob.LargeBlobAuthenticationInput#write(ByteArray)
746
       * LargeBlobAuthenticationInput#write(ByteArray)} were successfully stored on the
747
       * authenticator, associated with the specified credential.
748
       *
749
       * @return Empty if {@link LargeBlobAuthenticationInput#getWrite()} was not present. Otherwise
750
       *     <code>true</code> if and only if the value of {@link
751
       *     LargeBlobAuthenticationInput#getWrite()} was successfully stored by the authenticator.
752
       * @see <a
753
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargebloboutputs-written">§10.5.
754
       *     Large blob storage extension (largeBlob)</a>
755
       */
756
      public Optional<Boolean> getWritten() {
757 1 1. getWritten : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::getWritten → KILLED
        return Optional.ofNullable(written);
758
      }
759
    }
760
  }
761
762
  /**
763
   * Definitions for the Pseudo-random function extension (<code>prf</code>).
764
   *
765
   * @since 2.7.0
766
   * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
767
   *     Pseudo-random function extension (prf)</a>
768
   */
769
  public static class Prf {
770
    static final String EXTENSION_ID = "prf";
771
772
    /**
773
     * One or two inputs to or outputs from the pseudo-random function (PRF) associated with a
774
     * credential.
775
     *
776
     * <p>{@link #getFirst()} is always present, but {@link #getSecond()} is empty when only one
777
     * input or output was given.
778
     *
779
     * @since 2.7.0
780
     * @see #one(ByteArray)
781
     * @see #two(ByteArray, ByteArray)
782
     * @see #oneOrTwo(ByteArray, Optional)
783
     * @see <a
784
     *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfvalues">dictionary
785
     *     AuthenticationExtensionsPRFValues</a>
786
     * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
787
     *     Pseudo-random function extension (prf)</a>
788
     */
789
    @Value
790
    public static class PrfValues {
791
      /**
792
       * The first PRF input to evaluate, or the result of that evaluation.
793
       *
794
       * @since 2.7.0
795
       * @see <a
796
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfvalues-first">AuthenticationExtensionsPRFValues.first</a>
797
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
798
       *     Pseudo-random function extension (prf)</a>
799
       */
800
      @JsonProperty @NonNull private final ByteArray first;
801
802
      /**
803
       * The second PRF input to evaluate, if any, or the result of that evaluation.
804
       *
805
       * @since 2.7.0
806
       * @see <a
807
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfvalues-second">AuthenticationExtensionsPRFValues.second</a>
808
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
809
       *     Pseudo-random function extension (prf)</a>
810
       */
811
      @JsonProperty private final ByteArray second;
812
813
      @JsonCreator
814
      private PrfValues(
815 1 1. <init> : negated conditional → KILLED
          @JsonProperty("first") @NonNull final ByteArray first,
816
          @JsonProperty("second") final ByteArray second) {
817
        this.first = first;
818
        this.second = second;
819
      }
820
821
      /**
822
       * The second PRF input to evaluate, if any, or the result of that evaluation.
823
       *
824
       * @since 2.7.0
825
       * @see <a
826
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfvalues-second">AuthenticationExtensionsPRFValues.second</a>
827
       */
828
      public Optional<ByteArray> getSecond() {
829 1 1. getSecond : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfValues::getSecond → KILLED
        return Optional.ofNullable(second);
830
      }
831
832
      /**
833
       * Construct a {@link PrfValues} with a single PRF input or output.
834
       *
835
       * @param first the PRF input or output. Must not be null.
836
       * @since 2.7.0
837
       * @see <a
838
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfvalues">dictionary
839
       *     AuthenticationExtensionsPRFValues</a>
840
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
841
       *     Pseudo-random function extension (prf)</a>
842
       */
843 1 1. one : negated conditional → KILLED
      public static PrfValues one(@NonNull ByteArray first) {
844 1 1. one : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfValues::one → KILLED
        return new PrfValues(first, null);
845
      }
846
847
      /**
848
       * Construct a {@link PrfValues} with two PRF inputs or outputs.
849
       *
850
       * @param first the first PRF input or output. Must not be null.
851
       * @param second the second PRF input or output. Must not be null.
852
       * @since 2.7.0
853
       * @see <a
854
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfvalues">dictionary
855
       *     AuthenticationExtensionsPRFValues</a>
856
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
857
       *     Pseudo-random function extension (prf)</a>
858
       */
859 2 1. two : negated conditional → KILLED
2. two : negated conditional → KILLED
      public static PrfValues two(@NonNull ByteArray first, @NonNull ByteArray second) {
860 1 1. two : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfValues::two → KILLED
        return new PrfValues(first, second);
861
      }
862
863
      /**
864
       * Construct a {@link PrfValues} with two PRF inputs or outputs if <code>second</code> is
865
       * present, otherwise a {@link PrfValues} with one inputs or output.
866
       *
867
       * @param first the first PRF input or output. Must not be null.
868
       * @param second the second PRF input or output, if any. Must not be null, but may be empty.
869
       * @since 2.7.0
870
       * @see <a
871
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfvalues">dictionary
872
       *     AuthenticationExtensionsPRFValues</a>
873
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
874
       *     Pseudo-random function extension (prf)</a>
875
       */
876
      public static PrfValues oneOrTwo(
877 2 1. oneOrTwo : negated conditional → KILLED
2. oneOrTwo : negated conditional → KILLED
          @NonNull ByteArray first, @NonNull Optional<ByteArray> second) {
878 1 1. oneOrTwo : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfValues::oneOrTwo → KILLED
        return new PrfValues(first, second.orElse(null));
879
      }
880
    }
881
882
    /**
883
     * Inputs for the Pseudo-random function extension (<code>prf</code>) in registration
884
     * ceremonies.
885
     *
886
     * @since 2.7.0
887
     * @see <a
888
     *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfinputs">dictionary
889
     *     AuthenticationExtensionsPRFInputs</a>
890
     * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
891
     *     Pseudo-random function extension (prf)</a>
892
     */
893
    @Value
894
    public static class PrfRegistrationInput {
895
      /**
896
       * PRF inputs to evaluate immediately if possible. Note that not all authenticators support
897
       * this, in which case a follow-up authentication ceremony may be needed in order to evaluate
898
       * the PRF.
899
       *
900
       * @since 2.7.0
901
       * @see #eval(PrfValues)
902
       * @see <a
903
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-eval">AuthenticationExtensionsPRFInputs.eval</a>
904
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
905
       *     Pseudo-random function extension (prf)</a>
906
       */
907
      @JsonProperty private final PrfValues eval;
908
909
      @JsonCreator
910
      private PrfRegistrationInput(@JsonProperty("eval") PrfValues eval) {
911
        this.eval = eval;
912
      }
913
914
      /**
915
       * PRF inputs to evaluate immediately if possible. Note that not all authenticators support
916
       * this, in which case a follow-up authentication ceremony may be needed in order to evaluate
917
       * the PRF.
918
       *
919
       * @since 2.7.0
920
       * @see #eval(PrfValues)
921
       * @see <a
922
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-eval">AuthenticationExtensionsPRFInputs.eval</a>
923
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
924
       *     Pseudo-random function extension (prf)</a>
925
       */
926
      public Optional<PrfValues> getEval() {
927 1 1. getEval : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationInput::getEval → KILLED
        return Optional.ofNullable(eval);
928
      }
929
930
      /**
931
       * Enable PRF for the created credential, without evaluating the PRF at this time.
932
       *
933
       * @since 2.7.0
934
       * @see #eval(PrfValues)
935
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
936
       *     Pseudo-random function extension (prf)</a>
937
       */
938
      public static PrfRegistrationInput enable() {
939 1 1. enable : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationInput::enable → KILLED
        return new PrfRegistrationInput(null);
940
      }
941
942
      /**
943
       * Enable PRF for the created credential, and attempt to immediately evaluate the PRF with the
944
       * given inputs. Note that not all authenticators support this, in which case a follow-up
945
       * authentication ceremony may be needed in order to evaluate the PRF.
946
       *
947
       * @since 2.7.0
948
       * @see #enable()
949
       * @see #getEval()
950
       * @see <a
951
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-eval">AuthenticationExtensionsPRFInputs.eval</a>
952
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
953
       *     Pseudo-random function extension (prf)</a>
954
       */
955 1 1. eval : negated conditional → KILLED
      public static PrfRegistrationInput eval(@NonNull PrfValues eval) {
956 1 1. eval : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationInput::eval → KILLED
        return new PrfRegistrationInput(eval);
957
      }
958
    }
959
960
    /**
961
     * Outputs for the Pseudo-random function extension (<code>prf</code>) in registration
962
     * ceremonies.
963
     *
964
     * @since 2.7.0
965
     * @see <a
966
     *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfoutputs">dictionary
967
     *     AuthenticationExtensionsPRFOutputs</a>
968
     * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
969
     *     Pseudo-random function extension (prf)</a>
970
     */
971
    @Value
972
    public static class PrfRegistrationOutput {
973
974
      /**
975
       * <code>true</code> if, and only if, a PRF is available for use with the created credential.
976
       *
977
       * @since 2.7.0
978
       * @see <a
979
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfoutputs-enabled">AuthenticationExtensionsPRFOutputs.enabled</a>
980
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
981
       *     Pseudo-random function extension (prf)</a>
982
       */
983
      @JsonProperty private final Boolean enabled;
984
985
      /**
986
       * The results of evaluating the PRF for the inputs given in {@link
987
       * PrfRegistrationInput#getEval() eval}, if any.
988
       *
989
       * @since 2.7.0
990
       * @see <a
991
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfoutputs-results">AuthenticationExtensionsPRFOutputs.results</a>
992
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
993
       *     Pseudo-random function extension (prf)</a>
994
       */
995
      @JsonProperty private final PrfValues results;
996
997
      @JsonCreator
998
      PrfRegistrationOutput(
999
          @JsonProperty("enabled") Boolean enabled, @JsonProperty("results") PrfValues results) {
1000
        this.enabled = enabled;
1001
        this.results = results;
1002
      }
1003
1004
      /**
1005
       * <code>true</code> if, and only if, a PRF is available for use with the created credential.
1006
       *
1007
       * @since 2.7.0
1008
       * @see <a
1009
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfoutputs-enabled">AuthenticationExtensionsPRFOutputs.enabled</a>
1010
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1011
       *     Pseudo-random function extension (prf)</a>
1012
       */
1013
      public Optional<Boolean> getEnabled() {
1014 1 1. getEnabled : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationOutput::getEnabled → NO_COVERAGE
        return Optional.ofNullable(enabled);
1015
      }
1016
1017
      /**
1018
       * The results of evaluating the PRF for the inputs given in {@link
1019
       * PrfRegistrationInput#getEval() eval}, if any.
1020
       *
1021
       * @since 2.7.0
1022
       * @see <a
1023
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfoutputs-results">AuthenticationExtensionsPRFOutputs.results</a>
1024
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1025
       *     Pseudo-random function extension (prf)</a>
1026
       */
1027
      public Optional<PrfValues> getResults() {
1028 1 1. getResults : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationOutput::getResults → NO_COVERAGE
        return Optional.ofNullable(results);
1029
      }
1030
    }
1031
1032
    /**
1033
     * Inputs for the Pseudo-random function extension (<code>prf</code>) in authentication
1034
     * ceremonies.
1035
     *
1036
     * @since 2.7.0
1037
     * @see <a
1038
     *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfinputs">dictionary
1039
     *     AuthenticationExtensionsPRFInputs</a>
1040
     * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1041
     *     Pseudo-random function extension (prf)</a>
1042
     */
1043
    @Value
1044
    public static class PrfAuthenticationInput {
1045
      /**
1046
       * PRF inputs to use for any credential without a dedicated input listed in {@link
1047
       * #getEvalByCredential()}.
1048
       *
1049
       * @since 2.7.0
1050
       * @see #eval(PrfValues)
1051
       * @see #evalByCredentialWithFallback(Map, PrfValues)
1052
       * @see <a
1053
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-eval">AuthenticationExtensionsPRFInputs.eval</a>
1054
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1055
       *     Pseudo-random function extension (prf)</a>
1056
       */
1057
      @JsonProperty private final PrfValues eval;
1058
1059
      /**
1060
       * A map of credential IDs to PRF inputs to use for that credential. Credentials without a
1061
       * mapping here fall back to the inputs in {@link #getEval()} if present, otherwise no PRF is
1062
       * evaluated for those credentials.
1063
       *
1064
       * @since 2.7.0
1065
       * @see #evalByCredential(Map)
1066
       * @see #evalByCredentialWithFallback(Map, PrfValues)
1067
       * @see <a
1068
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-evalbycredential">AuthenticationExtensionsPRFInputs.evalByCredential</a>
1069
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1070
       *     Pseudo-random function extension (prf)</a>
1071
       */
1072
      @JsonProperty private final Map<ByteArray, PrfValues> evalByCredential;
1073
1074
      @JsonCreator
1075
      private PrfAuthenticationInput(
1076
          @JsonProperty("eval") PrfValues eval,
1077
          @JsonProperty("evalByCredential") Map<ByteArray, PrfValues> evalByCredential) {
1078
        this.eval = eval;
1079
        this.evalByCredential =
1080 1 1. <init> : negated conditional → KILLED
            evalByCredential == null ? null : Collections.unmodifiableMap(evalByCredential);
1081
      }
1082
1083
      /**
1084
       * PRF inputs to use for any credential without a dedicated input listed in {@link
1085
       * #getEvalByCredential()}.
1086
       *
1087
       * @since 2.7.0
1088
       * @see #eval(PrfValues)
1089
       * @see #evalByCredentialWithFallback(Map, PrfValues)
1090
       * @see <a
1091
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-eval">AuthenticationExtensionsPRFInputs.eval</a>
1092
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1093
       *     Pseudo-random function extension (prf)</a>
1094
       */
1095
      public Optional<PrfValues> getEval() {
1096 1 1. getEval : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::getEval → KILLED
        return Optional.ofNullable(eval);
1097
      }
1098
1099
      /**
1100
       * A map of credential IDs to PRF inputs to use for that credential. Credentials without a
1101
       * mapping here fall back to the inputs in {@link #getEval()} if present, otherwise no PRF is
1102
       * evaluated for those credentials.
1103
       *
1104
       * @since 2.7.0
1105
       * @see #evalByCredential(Map)
1106
       * @see #evalByCredentialWithFallback(Map, PrfValues)
1107
       * @see <a
1108
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-evalbycredential">AuthenticationExtensionsPRFInputs.evalByCredential</a>
1109
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1110
       *     Pseudo-random function extension (prf)</a>
1111
       */
1112
      public Optional<Map<ByteArray, PrfValues>> getEvalByCredential() {
1113 1 1. getEvalByCredential : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::getEvalByCredential → KILLED
        return Optional.ofNullable(evalByCredential);
1114
      }
1115
1116
      private static HashMap<ByteArray, PrfValues> descriptorsToIds(
1117
          Map<PublicKeyCredentialDescriptor, PrfValues> evalByCredential) {
1118 1 1. descriptorsToIds : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::descriptorsToIds → KILLED
        return evalByCredential.entrySet().stream()
1119
            .reduce(
1120
                new HashMap<>(),
1121
                (ebc, entry) -> {
1122
                  ebc.put(entry.getKey().getId(), entry.getValue());
1123 1 1. lambda$descriptorsToIds$0 : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::lambda$descriptorsToIds$0 → KILLED
                  return ebc;
1124
                },
1125
                (a, b) -> {
1126 1 1. lambda$descriptorsToIds$1 : removed call to java/util/HashMap::putAll → NO_COVERAGE
                  a.putAll(b);
1127 1 1. lambda$descriptorsToIds$1 : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::lambda$descriptorsToIds$1 → NO_COVERAGE
                  return a;
1128
                });
1129
      }
1130
1131
      /**
1132
       * Use the same PRF inputs for all credentials.
1133
       *
1134
       * @since 2.7.0
1135
       * @see #getEval()
1136
       * @see <a
1137
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-eval">AuthenticationExtensionsPRFInputs.eval</a>
1138
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1139
       *     Pseudo-random function extension (prf)</a>
1140
       */
1141 1 1. eval : negated conditional → KILLED
      public static PrfAuthenticationInput eval(@NonNull PrfValues eval) {
1142 1 1. eval : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::eval → KILLED
        return new PrfAuthenticationInput(eval, null);
1143
      }
1144
1145
      /**
1146
       * Use different PRF inputs for different credentials, and skip PRF evaluation for any
1147
       * credentials not present in the map.
1148
       *
1149
       * @since 2.7.0
1150
       * @see #getEvalByCredential()
1151
       * @see <a
1152
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-evalbycredential">AuthenticationExtensionsPRFInputs.evalByCredential</a>
1153
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1154
       *     Pseudo-random function extension (prf)</a>
1155
       */
1156
      public static PrfAuthenticationInput evalByCredential(
1157 1 1. evalByCredential : negated conditional → KILLED
          @NonNull Map<PublicKeyCredentialDescriptor, PrfValues> evalByCredential) {
1158 1 1. evalByCredential : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::evalByCredential → KILLED
        return new PrfAuthenticationInput(null, descriptorsToIds(evalByCredential));
1159
      }
1160
1161
      /**
1162
       * Use different PRF inputs for different credentials, and "fallback" inputs for any
1163
       * credentials not present in the map.
1164
       *
1165
       * @param evalByCredential a map of credential IDs to PRF inputs to use for that credential.
1166
       * @param eval "fallback" inputs to use for any credential not listed in <code>
1167
       *     evalByCredential</code>.
1168
       * @since 2.7.0
1169
       * @see #getEvalByCredential()
1170
       * @see #getEval() ()
1171
       * @see <a
1172
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-evalbycredential">AuthenticationExtensionsPRFInputs.evalByCredential</a>
1173
       * @see <a
1174
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfinputs-eval">AuthenticationExtensionsPRFInputs.eval</a>
1175
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1176
       *     Pseudo-random function extension (prf)</a>
1177
       */
1178
      public static PrfAuthenticationInput evalByCredentialWithFallback(
1179 1 1. evalByCredentialWithFallback : negated conditional → KILLED
          @NonNull Map<PublicKeyCredentialDescriptor, PrfValues> evalByCredential,
1180 1 1. evalByCredentialWithFallback : negated conditional → KILLED
          @NonNull PrfValues eval) {
1181 1 1. evalByCredentialWithFallback : replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::evalByCredentialWithFallback → KILLED
        return new PrfAuthenticationInput(eval, descriptorsToIds(evalByCredential));
1182
      }
1183
    }
1184
1185
    /**
1186
     * Outputs for the Pseudo-random function extension (<code>prf</code>) in authentication
1187
     * ceremonies.
1188
     *
1189
     * @since 2.7.0
1190
     * @see <a
1191
     *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dictdef-authenticationextensionsprfoutputs">dictionary
1192
     *     AuthenticationExtensionsPRFOutputs</a>
1193
     * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1194
     *     Pseudo-random function extension (prf)</a>
1195
     */
1196
    @Value
1197
    public static class PrfAuthenticationOutput {
1198
1199
      /**
1200
       * The results of evaluating the PRF for the inputs given in {@link
1201
       * PrfAuthenticationInput#getEval() eval} or {@link
1202
       * PrfAuthenticationInput#getEvalByCredential() evalByCredential}, if any.
1203
       *
1204
       * @since 2.7.0
1205
       * @see <a
1206
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfoutputs-results">AuthenticationExtensionsPRFOutputs.results</a>
1207
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1208
       *     Pseudo-random function extension (prf)</a>
1209
       */
1210
      @JsonProperty private final PrfValues results;
1211
1212
      @JsonCreator
1213
      PrfAuthenticationOutput(@JsonProperty("results") PrfValues results) {
1214
        this.results = results;
1215
      }
1216
1217
      /**
1218
       * The results of evaluating the PRF for the inputs given in {@link
1219
       * PrfAuthenticationInput#getEval() eval} or {@link
1220
       * PrfAuthenticationInput#getEvalByCredential() evalByCredential}, if any.
1221
       *
1222
       * @since 2.7.0
1223
       * @see <a
1224
       *     href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#dom-authenticationextensionsprfoutputs-results">AuthenticationExtensionsPRFOutputs.results</a>
1225
       * @see <a href="https://www.w3.org/TR/2025/WD-webauthn-3-20250127/#prf-extension">§10.1.4.
1226
       *     Pseudo-random function extension (prf)</a>
1227
       */
1228
      public Optional<PrfValues> getResults() {
1229 1 1. getResults : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationOutput::getResults → NO_COVERAGE
        return Optional.ofNullable(results);
1230
      }
1231
    }
1232
  }
1233
1234
  /**
1235
   * Definitions for the User Verification Method (<code>uvm</code>) Extension.
1236
   *
1237
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-uvm-extension">§10.3.
1238
   *     User Verification Method Extension (uvm)</a>
1239
   */
1240
  public static class Uvm {
1241
    static final String EXTENSION_ID = "uvm";
1242
1243
    /**
1244
     * A <code>uvmEntry</code> as defined in <a
1245
     * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-uvm-extension">§10.3. User
1246
     * Verification Method Extension (uvm)</a>.
1247
     *
1248
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-uvm-extension">§10.3.
1249
     *     User Verification Method Extension (uvm)</a>
1250
     * @see UserVerificationMethod
1251
     * @see KeyProtectionType
1252
     * @see MatcherProtectionType
1253
     */
1254
    @Value
1255
    public static class UvmEntry {
1256
      private final UserVerificationMethod userVerificationMethod;
1257
      private final KeyProtectionType keyProtectionType;
1258
      private final MatcherProtectionType matcherProtectionType;
1259
1260
      public UvmEntry(
1261
          @JsonProperty("userVerificationMethod") UserVerificationMethod userVerificationMethod,
1262
          @JsonProperty("keyProtectionType") KeyProtectionType keyProtectionType,
1263
          @JsonProperty("matcherProtectionType") MatcherProtectionType matcherProtectionType) {
1264
        this.userVerificationMethod = userVerificationMethod;
1265
        this.keyProtectionType = keyProtectionType;
1266
        this.matcherProtectionType = matcherProtectionType;
1267
      }
1268
    }
1269
1270
    static Optional<List<UvmEntry>> parseAuthenticatorExtensionOutput(CBORObject cbor) {
1271 1 1. parseAuthenticatorExtensionOutput : negated conditional → KILLED
      if (validateAuthenticatorExtensionOutput(cbor)) {
1272 1 1. parseAuthenticatorExtensionOutput : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Uvm::parseAuthenticatorExtensionOutput → KILLED
        return Optional.of(
1273
            cbor.get(EXTENSION_ID).getValues().stream()
1274
                .map(
1275
                    uvmEntry ->
1276 1 1. lambda$parseAuthenticatorExtensionOutput$0 : replaced return value with null for com/yubico/webauthn/data/Extensions$Uvm::lambda$parseAuthenticatorExtensionOutput$0 → KILLED
                        new UvmEntry(
1277
                            UserVerificationMethod.fromValue(uvmEntry.get(0).AsInt32Value()),
1278
                            KeyProtectionType.fromValue(
1279
                                uvmEntry.get(1).AsNumber().ToInt16IfExact()),
1280
                            MatcherProtectionType.fromValue(
1281
                                uvmEntry.get(2).AsNumber().ToInt16IfExact())))
1282
                .collect(Collectors.toList()));
1283
      } else {
1284
        return Optional.empty();
1285
      }
1286
    }
1287
1288
    private static boolean validateAuthenticatorExtensionOutput(CBORObject extensions) {
1289 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
      if (!extensions.ContainsKey(EXTENSION_ID)) {
1290 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → KILLED
        return false;
1291
      }
1292
1293
      CBORObject uvm = extensions.get(EXTENSION_ID);
1294 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
      if (uvm.getType() != CBORType.Array) {
1295
        log.debug(
1296
            "Invalid CBOR type for \"{}\" extension output: expected array, was: {}",
1297
            EXTENSION_ID,
1298
            uvm.getType());
1299 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
        return false;
1300
      }
1301
1302 4 1. validateAuthenticatorExtensionOutput : changed conditional boundary → SURVIVED
2. validateAuthenticatorExtensionOutput : changed conditional boundary → SURVIVED
3. validateAuthenticatorExtensionOutput : negated conditional → KILLED
4. validateAuthenticatorExtensionOutput : negated conditional → KILLED
      if (uvm.size() < 1 || uvm.size() > 3) {
1303
        log.debug(
1304
            "Invalid length \"{}\" extension output array: expected 1 to 3 (inclusive), was: {}",
1305
            EXTENSION_ID,
1306
            uvm.size());
1307 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
        return false;
1308
      }
1309
1310
      for (CBORObject entry : uvm.getValues()) {
1311 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
        if (entry.getType() != CBORType.Array) {
1312
          log.debug("Invalid CBOR type for uvmEntry: expected array, was: {}", entry.getType());
1313 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
          return false;
1314
        }
1315
1316 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
        if (entry.size() != 3) {
1317
          log.debug("Invalid length for uvmEntry: expected 3, was: {}", entry.size());
1318 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
          return false;
1319
        }
1320
1321
        for (CBORObject i : entry.getValues()) {
1322 2 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
2. validateAuthenticatorExtensionOutput : negated conditional → KILLED
          if (!(i.isNumber() && i.AsNumber().IsInteger())) {
1323
            log.debug("Invalid type for uvmEntry element: expected integer, was: {}", i.getType());
1324 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
            return false;
1325
          }
1326
        }
1327
      }
1328
1329 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with false for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → KILLED
      return true;
1330
    }
1331
  }
1332
}

Mutations

115

1.1
Location : getRk
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProperties$CredentialPropertiesOutput::getRk → KILLED

205

1.1
Location : fromCbor
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::fromCbor → KILLED

206

1.1
Location : lambda$fromCbor$0
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced boolean return with true for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromCbor$0 → KILLED

2.2
Location : lambda$fromCbor$0
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
negated conditional → KILLED

211

1.1
Location : fromJs
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::fromJs → KILLED

212

1.1
Location : lambda$fromJs$1
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced boolean return with false for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromJs$1 → KILLED

2.2
Location : lambda$fromJs$1
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced boolean return with true for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromJs$1 → KILLED

217

1.1
Location : fromJsonString
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

218

1.1
Location : fromJsonString
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::fromJsonString → KILLED

221

1.1
Location : lambda$fromJsonString$2
Killed by : none
replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionPolicy::lambda$fromJsonString$2 → NO_COVERAGE

281

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

282

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

309

1.1
Location : prefer
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

310

1.1
Location : prefer
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionInput::prefer → KILLED

339

1.1
Location : require
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

340

1.1
Location : require
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$CredentialProtection$CredentialProtectionInput::require → KILLED

399

1.1
Location : validateExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
removed call to java/util/Optional::ifPresent → KILLED

401

1.1
Location : lambda$validateExtensionOutput$0
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
negated conditional → KILLED

402

1.1
Location : lambda$validateExtensionOutput$0
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
negated conditional → KILLED

410

1.1
Location : lambda$validateExtensionOutput$0
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

421

1.1
Location : parseAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection::parseAuthenticatorExtensionOutput → KILLED

424

1.1
Location : lambda$parseAuthenticatorExtensionOutput$1
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced Integer return value with 0 for com/yubico/webauthn/data/Extensions$CredentialProtection::lambda$parseAuthenticatorExtensionOutput$1 → KILLED

2.2
Location : lambda$parseAuthenticatorExtensionOutput$1
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
negated conditional → KILLED

3.3
Location : lambda$parseAuthenticatorExtensionOutput$1
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
negated conditional → KILLED

427

1.1
Location : lambda$parseAuthenticatorExtensionOutput$2
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProtection::lambda$parseAuthenticatorExtensionOutput$2 → KILLED

532

1.1
Location : values
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with Collections.emptySet for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobRegistrationInput$LargeBlobSupport::values → KILLED

574

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

2.2
Location : <init>
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

3.3
Location : <init>
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

579

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

2.2
Location : <init>
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

594

1.1
Location : read
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::read → KILLED

607

1.1
Location : write
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

608

1.1
Location : write
Killed by : none
replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::write → SURVIVED

620

1.1
Location : getRead
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced boolean return with false for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getRead → KILLED

2.2
Location : getRead
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced boolean return with true for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getRead → KILLED

631

1.1
Location : getWrite
Killed by : none
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getWrite → SURVIVED

671

1.1
Location : supported
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobRegistrationOutput::supported → KILLED

707

1.1
Location : read
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::read → KILLED

723

1.1
Location : write
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::write → KILLED

740

1.1
Location : getBlob
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::getBlob → KILLED

757

1.1
Location : getWritten
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::getWritten → KILLED

815

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

829

1.1
Location : getSecond
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfValues::getSecond → KILLED

843

1.1
Location : one
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

844

1.1
Location : one
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfValues::one → KILLED

859

1.1
Location : two
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

2.2
Location : two
Killed by : com.yubico.webauthn.data.ExtensionsSpec
negated conditional → KILLED

860

1.1
Location : two
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfValues::two → KILLED

877

1.1
Location : oneOrTwo
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

2.2
Location : oneOrTwo
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

878

1.1
Location : oneOrTwo
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfValues::oneOrTwo → KILLED

927

1.1
Location : getEval
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationInput::getEval → KILLED

939

1.1
Location : enable
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationInput::enable → KILLED

955

1.1
Location : eval
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

956

1.1
Location : eval
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationInput::eval → KILLED

1014

1.1
Location : getEnabled
Killed by : none
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationOutput::getEnabled → NO_COVERAGE

1028

1.1
Location : getResults
Killed by : none
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfRegistrationOutput::getResults → NO_COVERAGE

1080

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

1096

1.1
Location : getEval
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::getEval → KILLED

1113

1.1
Location : getEvalByCredential
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::getEvalByCredential → KILLED

1118

1.1
Location : descriptorsToIds
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::descriptorsToIds → KILLED

1123

1.1
Location : lambda$descriptorsToIds$0
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::lambda$descriptorsToIds$0 → KILLED

1126

1.1
Location : lambda$descriptorsToIds$1
Killed by : none
removed call to java/util/HashMap::putAll → NO_COVERAGE

1127

1.1
Location : lambda$descriptorsToIds$1
Killed by : none
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::lambda$descriptorsToIds$1 → NO_COVERAGE

1141

1.1
Location : eval
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

1142

1.1
Location : eval
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::eval → KILLED

1157

1.1
Location : evalByCredential
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

1158

1.1
Location : evalByCredential
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::evalByCredential → KILLED

1179

1.1
Location : evalByCredentialWithFallback
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

1180

1.1
Location : evalByCredentialWithFallback
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

1181

1.1
Location : evalByCredentialWithFallback
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationInput::evalByCredentialWithFallback → KILLED

1229

1.1
Location : getResults
Killed by : none
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Prf$PrfAuthenticationOutput::getResults → NO_COVERAGE

1271

1.1
Location : parseAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

1272

1.1
Location : parseAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Uvm::parseAuthenticatorExtensionOutput → KILLED

1276

1.1
Location : lambda$parseAuthenticatorExtensionOutput$0
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
replaced return value with null for com/yubico/webauthn/data/Extensions$Uvm::lambda$parseAuthenticatorExtensionOutput$0 → KILLED

1289

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

1290

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → KILLED

1294

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

1299

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : none
replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE

1302

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : validateAuthenticatorExtensionOutput
Killed by : none
changed conditional boundary → SURVIVED

3.3
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

4.4
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

1307

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : none
replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE

1311

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

1313

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : none
replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE

1316

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

1318

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : none
replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE

1322

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

2.2
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
negated conditional → KILLED

1324

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : none
replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE

1329

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
replaced boolean return with false for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.0