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

Mutations

106

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

212

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

254

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

259

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

274

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

287

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

288

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

300

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

311

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

351

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

387

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

403

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

420

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

437

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

479

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

480

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

484

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

497

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

498

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

502

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

507

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

510

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

515

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

519

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

521

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

524

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

526

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

530

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

532

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

537

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