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.webauthn.AssertionResult;
10
import com.yubico.webauthn.AssertionResultV2;
11
import com.yubico.webauthn.RegistrationResult;
12
import com.yubico.webauthn.StartRegistrationOptions;
13
import com.yubico.webauthn.extension.uvm.KeyProtectionType;
14
import com.yubico.webauthn.extension.uvm.MatcherProtectionType;
15
import com.yubico.webauthn.extension.uvm.UserVerificationMethod;
16
import java.util.List;
17
import java.util.Optional;
18
import java.util.Set;
19
import java.util.stream.Collectors;
20
import java.util.stream.Stream;
21
import lombok.Builder;
22
import lombok.NonNull;
23
import lombok.Value;
24
import lombok.experimental.UtilityClass;
25
import lombok.extern.slf4j.Slf4j;
26
27
/** Definitions for WebAuthn extensions. */
28
@Slf4j
29
@UtilityClass
30
public class Extensions {
31
32
  /**
33
   * Definitions for the FIDO AppID Extension (<code>appid</code>).
34
   *
35
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-extension">§10.1.
36
   *     FIDO AppID Extension (appid)</a>
37
   */
38
  public static class Appid {
39
    static final String EXTENSION_ID = "appid";
40
  }
41
42
  /**
43
   * Definitions for the 10.2. FIDO AppID Exclusion Extension (<code>appidExclude</code>).
44
   *
45
   * @see <a
46
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-exclude-extension">10.2.
47
   *     FIDO AppID Exclusion Extension (appidExclude)</a>
48
   */
49
  public static class AppidExclude {
50
    static final String EXTENSION_ID = "appidExclude";
51
  }
52
53
  /**
54
   * Definitions for the Credential Properties Extension (<code>credProps</code>).
55
   *
56
   * @see <a
57
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-authenticator-credential-properties-extension">§10.4.
58
   *     Credential Properties Extension (credProps)</a>
59
   */
60
  public static class CredentialProperties {
61
    static final String EXTENSION_ID = "credProps";
62
63
    /**
64
     * Extension outputs for the Credential Properties Extension (<code>credProps</code>).
65
     *
66
     * @see <a
67
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-authenticator-credential-properties-extension">§10.4.
68
     *     Credential Properties Extension (credProps)</a>
69
     */
70
    @Value
71
    @Builder
72
    @JsonIgnoreProperties(ignoreUnknown = true)
73
    public static class CredentialPropertiesOutput {
74
      @JsonProperty("rk")
75
      private final Boolean rk;
76
77
      @JsonProperty("authenticatorDisplayName")
78
      private final String authenticatorDisplayName;
79
80
      @JsonCreator
81
      private CredentialPropertiesOutput(
82
          @JsonProperty("rk") Boolean rk,
83
          @JsonProperty("authenticatorDisplayName") String authenticatorDisplayName) {
84
        this.rk = rk;
85
        this.authenticatorDisplayName = authenticatorDisplayName;
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
       * This OPTIONAL property is a human-palatable description of the credential's managing
120
       * authenticator, chosen by the user.
121
       *
122
       * <p>If the application supports setting "nicknames" for registered credentials, then this
123
       * value may be a suitable default value for such a nickname.
124
       *
125
       * <p>In an authentication ceremony, if this value is different from the stored nickname, then
126
       * the application may want to offer the user to update the stored nickname to match this
127
       * value.
128
       *
129
       * @return A user-chosen or vendor-default display name for the credential, if available.
130
       *     Otherwise empty.
131
       * @see <a
132
       *     href="https://w3c.github.io/webauthn/#dom-credentialpropertiesoutput-authenticatordisplayname">
133
       *     <code>authenticatorDisplayName</code> in §10.1.3. Credential Properties Extension
134
       *     (credProps)</a>
135
       * @see RegistrationResult#getAuthenticatorDisplayName()
136
       * @see AssertionResult#getAuthenticatorDisplayName()
137
       * @see AssertionResultV2#getAuthenticatorDisplayName()
138
       * @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change
139
       *     as the standard matures.
140
       */
141
      @Deprecated
142
      public Optional<String> getAuthenticatorDisplayName() {
143 1 1. getAuthenticatorDisplayName : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$CredentialProperties$CredentialPropertiesOutput::getAuthenticatorDisplayName → KILLED
        return Optional.ofNullable(authenticatorDisplayName);
144
      }
145
    }
146
  }
147
148
  /**
149
   * Definitions for the Large blob storage extension (<code>largeBlob</code>).
150
   *
151
   * @see <a
152
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
153
   *     Large blob storage extension (largeBlob)</a>
154
   */
155
  public static class LargeBlob {
156
    static final String EXTENSION_ID = "largeBlob";
157
158
    /**
159
     * Extension inputs for the Large blob storage extension (<code>largeBlob</code>) in
160
     * registration ceremonies.
161
     *
162
     * @see <a
163
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
164
     *     Large blob storage extension (largeBlob)</a>
165
     */
166
    @Value
167
    public static class LargeBlobRegistrationInput {
168
      /**
169
       * The Relying Party's preference of whether the created credential should support the <code>
170
       * largeBlob</code> extension.
171
       */
172
      @JsonProperty private final LargeBlobSupport support;
173
174
      @JsonCreator
175
      public LargeBlobRegistrationInput(
176
          /**
177
           * The Relying Party's preference of whether the created credential should support the
178
           * <code>
179
           * largeBlob</code> extension.
180
           *
181
           * <p>Currently the only valid values are {@link LargeBlobSupport#REQUIRED} and {@link
182
           * LargeBlobSupport#PREFERRED}, but custom values MAY be constructed in case more values
183
           * are added in future revisions of the extension.
184
           */
185
          @JsonProperty("support") LargeBlobSupport support) {
186
        this.support = support;
187
      }
188
189
      /**
190
       * The known valid arguments for the Large blob storage extension (<code>largeBlob</code>)
191
       * input in registration ceremonies.
192
       *
193
       * <p>Currently the only valid values are {@link LargeBlobSupport#REQUIRED} and {@link
194
       * LargeBlobSupport#PREFERRED}, but custom values MAY be constructed in case more values are
195
       * added in future revisions of the extension.
196
       *
197
       * @see #REQUIRED
198
       * @see #PREFERRED
199
       * @see <a
200
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
201
       *     Large blob storage extension (largeBlob)</a>
202
       */
203
      @Value
204
      public static class LargeBlobSupport {
205
        /**
206
         * The authenticator used for registration MUST support the <code>largeBlob</code>
207
         * extension.
208
         *
209
         * <p>Note: If the client does not support the <code>largeBlob</code> extension, this
210
         * requirement MAY be ignored.
211
         *
212
         * <p>Note: CTAP authenticators only support <code>largeBlob</code> in combination with
213
         * {@link AuthenticatorSelectionCriteria#getResidentKey()} set to <code>REQUIRED</code> in
214
         * {@link StartRegistrationOptions#getAuthenticatorSelection()}.
215
         *
216
         * @see <a
217
         *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
218
         *     Large blob storage extension (largeBlob)</a>
219
         */
220
        public static final LargeBlobSupport REQUIRED = new LargeBlobSupport("required");
221
222
        /**
223
         * If the authenticator used for registration supports the <code>largeBlob</code> extension,
224
         * it will be enabled for the created credential. If not supported, the credential will be
225
         * created without large blob support.
226
         *
227
         * <p>Note: CTAP authenticators only support <code>largeBlob</code> in combination with
228
         * {@link AuthenticatorSelectionCriteria#getResidentKey()} set to <code>REQUIRED</code> in
229
         * {@link StartRegistrationOptions#getAuthenticatorSelection()}.
230
         *
231
         * @see <a
232
         *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
233
         *     Large blob storage extension (largeBlob)</a>
234
         */
235
        public static final LargeBlobSupport PREFERRED = new LargeBlobSupport("preferred");
236
237
        /**
238
         * The underlying string value of this {@link LargeBlobSupport} value.
239
         *
240
         * @see #REQUIRED
241
         * @see #PREFERRED
242
         */
243
        @JsonValue private final String value;
244
245
        /**
246
         * Returns a new {@link Set} containing the {@link #REQUIRED} and {@link #PREFERRED} values.
247
         */
248
        public static Set<LargeBlobSupport> values() {
249 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());
250
        }
251
      }
252
    }
253
254
    /**
255
     * Extension inputs for the Large blob storage extension (<code>largeBlob</code>) in
256
     * authentication ceremonies.
257
     *
258
     * <p>Use the {@link #read()} and {@link #write(ByteArray)} factory functions to construct this
259
     * type.
260
     *
261
     * @see <a
262
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
263
     *     Large blob storage extension (largeBlob)</a>
264
     */
265
    @Value
266
    public static class LargeBlobAuthenticationInput {
267
      /**
268
       * If <code>true</code>, indicates that the Relying Party would like to fetch the
269
       * previously-written blob associated with the asserted credential.
270
       *
271
       * @see #read()
272
       * @see <a
273
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
274
       *     Large blob storage extension (largeBlob)</a>
275
       */
276
      @JsonProperty private final boolean read;
277
278
      /**
279
       * An opaque byte string that the Relying Party wishes to store with the existing credential.
280
       *
281
       * @see #write(ByteArray)
282
       * @see <a
283
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-write">§10.5.
284
       *     Large blob storage extension (largeBlob)</a>
285
       */
286
      @JsonProperty private final ByteArray write;
287
288
      @JsonCreator
289
      private LargeBlobAuthenticationInput(
290
          @JsonProperty("read") final Boolean read, @JsonProperty("write") final ByteArray write) {
291 3 1. <init> : negated conditional → KILLED
2. <init> : negated conditional → KILLED
3. <init> : negated conditional → KILLED
        if (read != null && read && write != null) {
292
          throw new IllegalArgumentException(
293
              "Parameters \"read\" and \"write\" of largeBlob extension must not both be present.");
294
        }
295
296 2 1. <init> : negated conditional → KILLED
2. <init> : negated conditional → KILLED
        this.read = read != null && read;
297
        this.write = write;
298
      }
299
300
      /**
301
       * Configure the Large blob storage extension (<code>largeBlob</code>) to fetch the
302
       * previously-written blob associated with the asserted credential.
303
       *
304
       * <p>Mutually exclusive with {@link #write(ByteArray)}.
305
       *
306
       * @see <a
307
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
308
       *     Large blob storage extension (largeBlob)</a>
309
       */
310
      public static LargeBlobAuthenticationInput read() {
311 1 1. read : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::read → KILLED
        return new LargeBlobAuthenticationInput(true, null);
312
      }
313
314
      /**
315
       * Configure the Large blob storage extension (<code>largeBlob</code>) to store the given byte
316
       * array with the existing credential.
317
       *
318
       * <p>Mutually exclusive with {@link #read()}.
319
       *
320
       * @see <a
321
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-write">§10.5.
322
       *     Large blob storage extension (largeBlob)</a>
323
       */
324 1 1. write : negated conditional → KILLED
      public static LargeBlobAuthenticationInput write(@NonNull final ByteArray write) {
325 1 1. write : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::write → SURVIVED
        return new LargeBlobAuthenticationInput(false, write);
326
      }
327
328
      /**
329
       * @return <code>true</code> if the <code>read</code> property is set to <code>true</code>,
330
       *     <code>false</code> otherwise.
331
       * @see #read()
332
       * @see <a
333
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
334
       *     Large blob storage extension (largeBlob)</a>
335
       */
336
      public boolean getRead() {
337 2 1. getRead : replaced boolean return with true for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getRead → KILLED
2. getRead : replaced boolean return with false for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getRead → KILLED
        return read;
338
      }
339
340
      /**
341
       * @return The value of the <code>write</code> property if configured, empty otherwise.
342
       * @see #write(ByteArray)
343
       * @see <a
344
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargeblobinputs-read">§10.5.
345
       *     Large blob storage extension (largeBlob)</a>
346
       */
347
      public Optional<ByteArray> getWrite() {
348 1 1. getWrite : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getWrite → SURVIVED
        return Optional.ofNullable(write);
349
      }
350
    }
351
352
    /**
353
     * Extension outputs for the Large blob storage extension (<code>largeBlob</code>) in
354
     * registration ceremonies.
355
     *
356
     * <p>Use the {@link #supported(boolean)} factory function to construct this type.
357
     *
358
     * @see <a
359
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
360
     *     Large blob storage extension (largeBlob)</a>
361
     */
362
    @Value
363
    public static class LargeBlobRegistrationOutput {
364
      /**
365
       * <code>true</code> if, and only if, the created credential supports storing large blobs.
366
       *
367
       * @see <a
368
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargebloboutputs-supported">§10.5.
369
       *     Large blob storage extension (largeBlob)</a>
370
       * @see LargeBlobRegistrationInput#getSupport()
371
       */
372
      @JsonProperty private final boolean supported;
373
374
      @JsonCreator
375
      private LargeBlobRegistrationOutput(@JsonProperty("supported") boolean supported) {
376
        this.supported = supported;
377
      }
378
379
      /**
380
       * Create a Large blob storage extension output with the <code>supported</code> output set to
381
       * the given value.
382
       *
383
       * @see <a
384
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dictdef-authenticationextensionslargebloboutputs">
385
       *     dictionary AuthenticationExtensionsLargeBlobOutputs</a>
386
       */
387
      public static LargeBlobRegistrationOutput supported(boolean supported) {
388 1 1. supported : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobRegistrationOutput::supported → KILLED
        return new LargeBlobRegistrationOutput(supported);
389
      }
390
    }
391
392
    /**
393
     * Extension outputs for the Large blob storage extension (<code>largeBlob</code>) in
394
     * authentication ceremonies.
395
     *
396
     * @see <a
397
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">§10.5.
398
     *     Large blob storage extension (largeBlob)</a>
399
     */
400
    @Value
401
    public static class LargeBlobAuthenticationOutput {
402
      @JsonProperty private final ByteArray blob;
403
      @JsonProperty private final Boolean written;
404
405
      @JsonCreator
406
      private LargeBlobAuthenticationOutput(
407
          @JsonProperty("blob") ByteArray blob, @JsonProperty("written") Boolean written) {
408
        this.blob = blob;
409
        this.written = written;
410
      }
411
412
      /**
413
       * Create a Large blob storage extension output with the <code>blob</code> output set to the
414
       * given value.
415
       *
416
       * <p>This corresponds to the extension input {@link LargeBlobAuthenticationInput#read()
417
       * LargeBlobAuthenticationInput.read()}.
418
       *
419
       * @see <a
420
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dictdef-authenticationextensionslargebloboutputs">
421
       *     dictionary AuthenticationExtensionsLargeBlobOutputs</a>
422
       */
423
      public static LargeBlobAuthenticationOutput read(final ByteArray blob) {
424 1 1. read : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::read → KILLED
        return new LargeBlobAuthenticationOutput(blob, null);
425
      }
426
427
      /**
428
       * Create a Large blob storage extension output with the <code>written</code> output set to
429
       * the given value.
430
       *
431
       * <p>This corresponds to the extension input {@link
432
       * LargeBlobAuthenticationInput#write(ByteArray)
433
       * LargeBlobAuthenticationInput.write(ByteArray)}.
434
       *
435
       * @see <a
436
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dictdef-authenticationextensionslargebloboutputs">
437
       *     dictionary AuthenticationExtensionsLargeBlobOutputs</a>
438
       */
439
      public static LargeBlobAuthenticationOutput write(final boolean write) {
440 1 1. write : replaced return value with null for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::write → KILLED
        return new LargeBlobAuthenticationOutput(null, write);
441
      }
442
443
      /**
444
       * The opaque byte string that was associated with the credential identified by {@link
445
       * PublicKeyCredential#getId()}. Only valid if {@link LargeBlobAuthenticationInput#getRead()}
446
       * was <code>true</code>.
447
       *
448
       * @return A present {@link Optional} if {@link LargeBlobAuthenticationInput#getRead()} was
449
       *     <code>true</code> and the blob content was successfully read. Otherwise (if {@link
450
       *     LargeBlobAuthenticationInput#getRead()} was <code>false</code> or the content failed to
451
       *     be read) an empty {@link Optional}.
452
       * @see <a
453
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargebloboutputs-blob">§10.5.
454
       *     Large blob storage extension (largeBlob)</a>
455
       */
456
      public Optional<ByteArray> getBlob() {
457 1 1. getBlob : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::getBlob → KILLED
        return Optional.ofNullable(blob);
458
      }
459
460
      /**
461
       * A boolean that indicates that the contents of {@link
462
       * LargeBlob.LargeBlobAuthenticationInput#write(ByteArray)
463
       * LargeBlobAuthenticationInput#write(ByteArray)} were successfully stored on the
464
       * authenticator, associated with the specified credential.
465
       *
466
       * @return Empty if {@link LargeBlobAuthenticationInput#getWrite()} was not present. Otherwise
467
       *     <code>true</code> if and only if the value of {@link
468
       *     LargeBlobAuthenticationInput#getWrite()} was successfully stored by the authenticator.
469
       * @see <a
470
       *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticationextensionslargebloboutputs-written">§10.5.
471
       *     Large blob storage extension (largeBlob)</a>
472
       */
473
      public Optional<Boolean> getWritten() {
474 1 1. getWritten : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationOutput::getWritten → KILLED
        return Optional.ofNullable(written);
475
      }
476
    }
477
  }
478
479
  /**
480
   * Definitions for the User Verification Method (<code>uvm</code>) Extension.
481
   *
482
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-uvm-extension">§10.3.
483
   *     User Verification Method Extension (uvm)</a>
484
   */
485
  public static class Uvm {
486
    static final String EXTENSION_ID = "uvm";
487
488
    /**
489
     * A <code>uvmEntry</code> as defined in <a
490
     * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-uvm-extension">§10.3. User
491
     * Verification Method Extension (uvm)</a>.
492
     *
493
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-uvm-extension">§10.3.
494
     *     User Verification Method Extension (uvm)</a>
495
     * @see UserVerificationMethod
496
     * @see KeyProtectionType
497
     * @see MatcherProtectionType
498
     */
499
    @Value
500
    public static class UvmEntry {
501
      private final UserVerificationMethod userVerificationMethod;
502
      private final KeyProtectionType keyProtectionType;
503
      private final MatcherProtectionType matcherProtectionType;
504
505
      public UvmEntry(
506
          @JsonProperty("userVerificationMethod") UserVerificationMethod userVerificationMethod,
507
          @JsonProperty("keyProtectionType") KeyProtectionType keyProtectionType,
508
          @JsonProperty("matcherProtectionType") MatcherProtectionType matcherProtectionType) {
509
        this.userVerificationMethod = userVerificationMethod;
510
        this.keyProtectionType = keyProtectionType;
511
        this.matcherProtectionType = matcherProtectionType;
512
      }
513
    }
514
515
    static Optional<List<UvmEntry>> parseAuthenticatorExtensionOutput(CBORObject cbor) {
516 1 1. parseAuthenticatorExtensionOutput : negated conditional → KILLED
      if (validateAuthenticatorExtensionOutput(cbor)) {
517 1 1. parseAuthenticatorExtensionOutput : replaced return value with Optional.empty for com/yubico/webauthn/data/Extensions$Uvm::parseAuthenticatorExtensionOutput → KILLED
        return Optional.of(
518
            cbor.get(EXTENSION_ID).getValues().stream()
519
                .map(
520
                    uvmEntry ->
521 1 1. lambda$parseAuthenticatorExtensionOutput$0 : replaced return value with null for com/yubico/webauthn/data/Extensions$Uvm::lambda$parseAuthenticatorExtensionOutput$0 → KILLED
                        new UvmEntry(
522
                            UserVerificationMethod.fromValue(uvmEntry.get(0).AsInt32Value()),
523
                            KeyProtectionType.fromValue(
524
                                uvmEntry.get(1).AsNumber().ToInt16IfExact()),
525
                            MatcherProtectionType.fromValue(
526
                                uvmEntry.get(2).AsNumber().ToInt16IfExact())))
527
                .collect(Collectors.toList()));
528
      } else {
529
        return Optional.empty();
530
      }
531
    }
532
533
    private static boolean validateAuthenticatorExtensionOutput(CBORObject extensions) {
534 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
      if (!extensions.ContainsKey(EXTENSION_ID)) {
535 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
        return false;
536
      }
537
538
      CBORObject uvm = extensions.get(EXTENSION_ID);
539 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
      if (uvm.getType() != CBORType.Array) {
540
        log.debug(
541
            "Invalid CBOR type for \"{}\" extension output: expected array, was: {}",
542
            EXTENSION_ID,
543
            uvm.getType());
544 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
        return false;
545
      }
546
547 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) {
548
        log.debug(
549
            "Invalid length \"{}\" extension output array: expected 1 to 3 (inclusive), was: {}",
550
            EXTENSION_ID,
551
            uvm.size());
552 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
        return false;
553
      }
554
555
      for (CBORObject entry : uvm.getValues()) {
556 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
        if (entry.getType() != CBORType.Array) {
557
          log.debug("Invalid CBOR type for uvmEntry: expected array, was: {}", entry.getType());
558 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
          return false;
559
        }
560
561 1 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
        if (entry.size() != 3) {
562
          log.debug("Invalid length for uvmEntry: expected 3, was: {}", entry.size());
563 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
          return false;
564
        }
565
566
        for (CBORObject i : entry.getValues()) {
567 2 1. validateAuthenticatorExtensionOutput : negated conditional → KILLED
2. validateAuthenticatorExtensionOutput : negated conditional → KILLED
          if (!(i.isNumber() && i.AsNumber().IsInteger())) {
568
            log.debug("Invalid type for uvmEntry element: expected integer, was: {}", i.getType());
569 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with true for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → NO_COVERAGE
            return false;
570
          }
571
        }
572
      }
573
574 1 1. validateAuthenticatorExtensionOutput : replaced boolean return with false for com/yubico/webauthn/data/Extensions$Uvm::validateAuthenticatorExtensionOutput → KILLED
      return true;
575
    }
576
  }
577
}

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

143

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

249

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

291

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

296

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

311

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

324

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

325

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

337

1.1
Location : getRead
Killed by : com.yubico.webauthn.data.ExtensionsSpec
replaced boolean return with true 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 false for com/yubico/webauthn/data/Extensions$LargeBlob$LargeBlobAuthenticationInput::getRead → KILLED

348

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

388

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

424

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

440

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

457

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

474

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

516

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

517

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

521

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

534

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

535

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

539

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

544

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

547

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

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

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

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

552

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

556

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

558

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

561

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

563

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

567

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

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

569

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

574

1.1
Location : validateAuthenticatorExtensionOutput
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
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