FinishAssertionSteps.java

1
// Copyright (c) 2018, Yubico AB
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are met:
6
//
7
// 1. Redistributions of source code must retain the above copyright notice, this
8
//    list of conditions and the following disclaimer.
9
//
10
// 2. Redistributions in binary form must reproduce the above copyright notice,
11
//    this list of conditions and the following disclaimer in the documentation
12
//    and/or other materials provided with the distribution.
13
//
14
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25
package com.yubico.webauthn;
26
27
import static com.yubico.internal.util.ExceptionUtil.assertTrue;
28
29
import com.yubico.internal.util.OptionalUtil;
30
import com.yubico.webauthn.data.AuthenticatorAssertionResponse;
31
import com.yubico.webauthn.data.ByteArray;
32
import com.yubico.webauthn.data.COSEAlgorithmIdentifier;
33
import com.yubico.webauthn.data.ClientAssertionExtensionOutputs;
34
import com.yubico.webauthn.data.CollectedClientData;
35
import com.yubico.webauthn.data.PublicKeyCredential;
36
import com.yubico.webauthn.data.UserVerificationRequirement;
37
import com.yubico.webauthn.exception.InvalidSignatureCountException;
38
import com.yubico.webauthn.extension.appid.AppId;
39
import java.io.IOException;
40
import java.security.NoSuchAlgorithmException;
41
import java.security.PublicKey;
42
import java.security.spec.InvalidKeySpecException;
43
import java.util.Optional;
44
import java.util.Set;
45
import lombok.AllArgsConstructor;
46
import lombok.Value;
47
import lombok.extern.slf4j.Slf4j;
48
49
@Slf4j
50
@AllArgsConstructor
51
final class FinishAssertionSteps<C extends CredentialRecord> {
52
53
  private static final String CLIENT_DATA_TYPE = "webauthn.get";
54
  private static final String SPC_CLIENT_DATA_TYPE = "payment.get";
55
56
  private final AssertionRequest request;
57
  private final PublicKeyCredential<AuthenticatorAssertionResponse, ClientAssertionExtensionOutputs>
58
      response;
59
  private final Optional<ByteArray> callerTokenBindingId;
60
  private final Set<String> origins;
61
  private final String rpId;
62
  private final CredentialRepositoryV2<C> credentialRepositoryV2;
63
  private final Optional<UsernameRepository> usernameRepository;
64
  private final boolean allowOriginPort;
65
  private final boolean allowOriginSubdomain;
66
  private final boolean validateSignatureCounter;
67
  private final boolean isSecurePaymentConfirmation;
68
69
  static FinishAssertionSteps<RegisteredCredential> fromV1(
70
      RelyingParty rp, FinishAssertionOptions options) {
71
    final CredentialRepository credRepo = rp.getCredentialRepository();
72
    final CredentialRepositoryV1ToV2Adapter credRepoV2 =
73
        new CredentialRepositoryV1ToV2Adapter(credRepo);
74 1 1. fromV1 : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::fromV1 → KILLED
    return new FinishAssertionSteps<>(
75
        options.getRequest(),
76
        options.getResponse(),
77
        options.getCallerTokenBindingId(),
78
        rp.getOrigins(),
79
        rp.getIdentity().getId(),
80
        credRepoV2,
81
        Optional.of(credRepoV2),
82
        rp.isAllowOriginPort(),
83
        rp.isAllowOriginSubdomain(),
84
        rp.isValidateSignatureCounter(),
85
        options.isSecurePaymentConfirmation());
86
  }
87
88
  FinishAssertionSteps(RelyingPartyV2<C> rp, FinishAssertionOptions options) {
89
    this(
90
        options.getRequest(),
91
        options.getResponse(),
92
        options.getCallerTokenBindingId(),
93
        rp.getOrigins(),
94
        rp.getIdentity().getId(),
95
        rp.getCredentialRepository(),
96
        Optional.ofNullable(rp.getUsernameRepository()),
97
        rp.isAllowOriginPort(),
98
        rp.isAllowOriginSubdomain(),
99
        rp.isValidateSignatureCounter(),
100
        options.isSecurePaymentConfirmation());
101
  }
102
103
  private Optional<String> getUsernameForUserHandle(final ByteArray userHandle) {
104 2 1. getUsernameForUserHandle : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps::getUsernameForUserHandle → KILLED
2. lambda$getUsernameForUserHandle$0 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps::lambda$getUsernameForUserHandle$0 → KILLED
    return usernameRepository.flatMap(unameRepo -> unameRepo.getUsernameForUserHandle(userHandle));
105
  }
106
107
  public Step5 begin() {
108 1 1. begin : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::begin → KILLED
    return new Step5();
109
  }
110
111
  public AssertionResult run() throws InvalidSignatureCountException {
112 1 1. run : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::run → KILLED
    return begin().run();
113
  }
114
115
  public AssertionResultV2<C> runV2() throws InvalidSignatureCountException {
116 1 1. runV2 : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::runV2 → KILLED
    return begin().runV2();
117
  }
118
119
  interface Step<C extends CredentialRecord, Next extends Step<C, ?>> {
120
    Next nextStep();
121
122
    void validate() throws InvalidSignatureCountException;
123
124
    default Optional<AssertionResult> result() {
125
      return Optional.empty();
126
    }
127
128
    default Optional<AssertionResultV2<C>> resultV2() {
129
      return Optional.empty();
130
    }
131
132
    default Next next() throws InvalidSignatureCountException {
133 1 1. next : removed call to com/yubico/webauthn/FinishAssertionSteps$Step::validate → KILLED
      validate();
134 1 1. next : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::next → KILLED
      return nextStep();
135
    }
136
137
    default AssertionResult run() throws InvalidSignatureCountException {
138 1 1. run : negated conditional → KILLED
      if (result().isPresent()) {
139 1 1. run : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::run → KILLED
        return result().get();
140
      } else {
141 1 1. run : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::run → KILLED
        return next().run();
142
      }
143
    }
144
145
    default AssertionResultV2<C> runV2() throws InvalidSignatureCountException {
146 1 1. runV2 : negated conditional → KILLED
      if (resultV2().isPresent()) {
147 1 1. runV2 : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::runV2 → KILLED
        return resultV2().get();
148
      } else {
149 1 1. runV2 : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::runV2 → KILLED
        return next().runV2();
150
      }
151
    }
152
  }
153
154
  // Steps 1 through 4 are to create the request and run the client-side part
155
156
  @Value
157
  class Step5 implements Step<C, Step6> {
158
    @Override
159
    public Step6 nextStep() {
160 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step5::nextStep → KILLED
      return new Step6();
161
    }
162
163
    @Override
164
    public void validate() {
165
      request
166
          .getPublicKeyCredentialRequestOptions()
167
          .getAllowCredentials()
168 2 1. lambda$validate$0 : negated conditional → KILLED
2. lambda$validate$0 : replaced boolean return with true for com/yubico/webauthn/FinishAssertionSteps$Step5::lambda$validate$0 → KILLED
          .filter(allowCredentials -> !allowCredentials.isEmpty())
169 1 1. validate : removed call to java/util/Optional::ifPresent → KILLED
          .ifPresent(
170
              allowed -> {
171 1 1. lambda$validate$2 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
                assertTrue(
172 2 1. lambda$validate$1 : replaced boolean return with false for com/yubico/webauthn/FinishAssertionSteps$Step5::lambda$validate$1 → KILLED
2. lambda$validate$1 : replaced boolean return with true for com/yubico/webauthn/FinishAssertionSteps$Step5::lambda$validate$1 → KILLED
                    allowed.stream().anyMatch(allow -> allow.getId().equals(response.getId())),
173
                    "Unrequested credential ID: %s",
174
                    response.getId());
175
              });
176
    }
177
  }
178
179
  @Value
180
  class Step6 implements Step<C, Step7> {
181
182
    private final Optional<ByteArray> requestedUserHandle;
183
    private final Optional<String> requestedUsername;
184
    private final Optional<ByteArray> responseUserHandle;
185
186
    private final Optional<ByteArray> effectiveRequestUserHandle;
187
    private final Optional<String> effectiveRequestUsername;
188
    private final boolean userHandleDerivedFromUsername;
189
190
    private final Optional<ByteArray> finalUserHandle;
191
    private final Optional<String> finalUsername;
192
    private final Optional<C> registration;
193
194
    public Step6() {
195
      requestedUserHandle = request.getUserHandle();
196
      requestedUsername = request.getUsername();
197
      responseUserHandle = response.getResponse().getUserHandle();
198
199
      effectiveRequestUserHandle =
200
          OptionalUtil.orElseOptional(
201
              requestedUserHandle,
202
              () ->
203 1 1. lambda$new$1 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$1 → KILLED
                  usernameRepository.flatMap(
204 1 1. lambda$new$0 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$0 → KILLED
                      unr -> requestedUsername.flatMap(unr::getUserHandleForUsername)));
205
206
      effectiveRequestUsername =
207
          OptionalUtil.orElseOptional(
208
              requestedUsername,
209
              () ->
210 2 1. lambda$new$3 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$3 → KILLED
2. lambda$new$2 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$2 → KILLED
                  requestedUserHandle.flatMap(FinishAssertionSteps.this::getUsernameForUserHandle));
211
212
      userHandleDerivedFromUsername =
213 2 1. <init> : negated conditional → SURVIVED
2. <init> : negated conditional → KILLED
          !requestedUserHandle.isPresent() && effectiveRequestUserHandle.isPresent();
214
215
      finalUserHandle = OptionalUtil.orOptional(effectiveRequestUserHandle, responseUserHandle);
216
      finalUsername =
217
          OptionalUtil.orElseOptional(
218
              effectiveRequestUsername,
219 2 1. lambda$new$5 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$5 → KILLED
2. lambda$new$4 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$4 → KILLED
              () -> finalUserHandle.flatMap(FinishAssertionSteps.this::getUsernameForUserHandle));
220
221
      registration =
222 1 1. lambda$new$6 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$6 → KILLED
          finalUserHandle.flatMap(uh -> credentialRepositoryV2.lookup(response.getId(), uh));
223
    }
224
225
    @Override
226
    public Step7 nextStep() {
227 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step6::nextStep → KILLED
      return new Step7(finalUsername, finalUserHandle.get(), registration);
228
    }
229
230
    @Override
231
    public void validate() {
232 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
      assertTrue(
233 2 1. validate : negated conditional → KILLED
2. validate : negated conditional → KILLED
          !(request.getUsername().isPresent() && !usernameRepository.isPresent()),
234
          "Cannot set request username when usernameRepository is not configured.");
235
236 1 1. validate : removed call to java/util/Optional::ifPresent → KILLED
      requestedUsername.ifPresent(
237
          reqUsername ->
238 1 1. lambda$validate$7 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
              assertTrue(
239
                  effectiveRequestUserHandle.isPresent(), "Unknown username: %s", reqUsername));
240
241 1 1. validate : removed call to java/util/Optional::ifPresent → SURVIVED
      requestedUserHandle.ifPresent(
242
          reqUserHandle -> {
243 1 1. lambda$validate$8 : negated conditional → KILLED
            if (usernameRepository.isPresent()) {
244 1 1. lambda$validate$8 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
              assertTrue(
245
                  effectiveRequestUsername.isPresent(), "Unknown user handle: %s", reqUserHandle);
246
            }
247
          });
248
249 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
      assertTrue(
250
          finalUserHandle.isPresent(),
251
          "Could not identify user to authenticate: none of requested username, requested user handle or response user handle are set.");
252
253 1 1. validate : negated conditional → KILLED
      if (usernameRepository.isPresent()) {
254 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
        assertTrue(
255
            finalUsername.isPresent(), "Unknown username for user handle: %s", finalUserHandle);
256
      }
257
258 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(registration.isPresent(), "Unknown credential: %s", response.getId());
259
260 1 1. validate : removed call to java/util/Optional::ifPresent → KILLED
      effectiveRequestUserHandle.ifPresent(
261
          reqUserHandle -> {
262
            final String reqUserHandleDescription =
263 1 1. lambda$validate$10 : negated conditional → KILLED
                userHandleDerivedFromUsername
264
                    ? String.format(
265
                        "%s (derived from username: %s)", reqUserHandle, requestedUsername.get())
266
                    : reqUserHandle.toString();
267 1 1. lambda$validate$10 : removed call to java/util/Optional::ifPresent → KILLED
            responseUserHandle.ifPresent(
268
                respUserHandle -> {
269 1 1. lambda$validate$9 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
                  assertTrue(
270
                      reqUserHandle.equals(respUserHandle),
271
                      "User handle in request (%s) does not match user handle in response (%s).",
272
                      reqUserHandleDescription,
273
                      respUserHandle);
274
                });
275
276 1 1. lambda$validate$10 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
            assertTrue(
277
                registration.get().getUserHandle().equals(reqUserHandle),
278
                "User handle %s does not own credential %s",
279
                reqUserHandleDescription,
280
                response.getId());
281
          });
282
283 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
284
          finalUserHandle.get().equals(registration.get().getUserHandle()),
285
          "User handle %s does not own credential %s",
286
          finalUserHandle.get(),
287
          registration.get().getUserHandle());
288
    }
289
  }
290
291
  @Value
292
  class Step7 implements Step<C, Step8> {
293
    private final Optional<String> username;
294
    private final ByteArray userHandle;
295
    private final Optional<C> credential;
296
297
    @Override
298
    public Step8 nextStep() {
299 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step7::nextStep → KILLED
      return new Step8(username, credential.get());
300
    }
301
302
    @Override
303
    public void validate() {
304 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
305
          credential.isPresent(),
306
          "Unknown credential. Credential ID: %s, user handle: %s",
307
          response.getId(),
308
          userHandle);
309
    }
310
  }
311
312
  @Value
313
  class Step8 implements Step<C, Step10> {
314
315
    private final Optional<String> username;
316
    private final C credential;
317
318
    @Override
319
    public void validate() {
320 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(clientData() != null, "Missing client data.");
321 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(authenticatorData() != null, "Missing authenticator data.");
322 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(signature() != null, "Missing signature.");
323
    }
324
325
    @Override
326
    public Step10 nextStep() {
327 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::nextStep → KILLED
      return new Step10(username, credential);
328
    }
329
330
    public ByteArray authenticatorData() {
331 1 1. authenticatorData : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::authenticatorData → KILLED
      return response.getResponse().getAuthenticatorData();
332
    }
333
334
    public ByteArray clientData() {
335 1 1. clientData : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::clientData → KILLED
      return response.getResponse().getClientDataJSON();
336
    }
337
338
    public ByteArray signature() {
339 1 1. signature : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::signature → KILLED
      return response.getResponse().getSignature();
340
    }
341
  }
342
343
  // Nothing to do for step 9
344
345
  @Value
346
  class Step10 implements Step<C, Step11> {
347
    private final Optional<String> username;
348
    private final C credential;
349
350
    @Override
351
    public void validate() {
352 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(clientData() != null, "Missing client data.");
353
    }
354
355
    @Override
356
    public Step11 nextStep() {
357 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step10::nextStep → KILLED
      return new Step11(username, credential, clientData());
358
    }
359
360
    public CollectedClientData clientData() {
361 1 1. clientData : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step10::clientData → KILLED
      return response.getResponse().getClientData();
362
    }
363
  }
364
365
  @Value
366
  class Step11 implements Step<C, Step12> {
367
    private final Optional<String> username;
368
    private final C credential;
369
    private final CollectedClientData clientData;
370
371
    @Override
372
    public void validate() {
373
      final String expectedType =
374 1 1. validate : negated conditional → KILLED
          isSecurePaymentConfirmation ? SPC_CLIENT_DATA_TYPE : CLIENT_DATA_TYPE;
375 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
376
          expectedType.equals(clientData.getType()),
377
          "The \"type\" in the client data must be exactly \"%s\", was: %s",
378
          expectedType,
379
          clientData.getType());
380
    }
381
382
    @Override
383
    public Step12 nextStep() {
384 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step11::nextStep → KILLED
      return new Step12(username, credential);
385
    }
386
  }
387
388
  @Value
389
  class Step12 implements Step<C, Step13> {
390
    private final Optional<String> username;
391
    private final C credential;
392
393
    @Override
394
    public void validate() {
395 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
396
          request
397
              .getPublicKeyCredentialRequestOptions()
398
              .getChallenge()
399
              .equals(response.getResponse().getClientData().getChallenge()),
400
          "Incorrect challenge.");
401
    }
402
403
    @Override
404
    public Step13 nextStep() {
405 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step12::nextStep → KILLED
      return new Step13(username, credential);
406
    }
407
  }
408
409
  @Value
410
  class Step13 implements Step<C, Step14> {
411
    private final Optional<String> username;
412
    private final C credential;
413
414
    @Override
415
    public void validate() {
416
      final String responseOrigin = response.getResponse().getClientData().getOrigin();
417 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
418
          OriginMatcher.isAllowed(responseOrigin, origins, allowOriginPort, allowOriginSubdomain),
419
          "Incorrect origin, please see the RelyingParty.origins setting: %s",
420
          responseOrigin);
421
    }
422
423
    @Override
424
    public Step14 nextStep() {
425 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step13::nextStep → KILLED
      return new Step14(username, credential);
426
    }
427
  }
428
429
  @Value
430
  class Step14 implements Step<C, Step15> {
431
    private final Optional<String> username;
432
    private final C credential;
433
434
    @Override
435
    public void validate() {
436
      TokenBindingValidator.validate(
437
          response.getResponse().getClientData().getTokenBinding(), callerTokenBindingId);
438
    }
439
440
    @Override
441
    public Step15 nextStep() {
442 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step14::nextStep → KILLED
      return new Step15(username, credential);
443
    }
444
  }
445
446
  @Value
447
  class Step15 implements Step<C, Step16> {
448
    private final Optional<String> username;
449
    private final C credential;
450
451
    @Override
452
    public void validate() {
453
      try {
454 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
        assertTrue(
455
            Crypto.sha256(rpId)
456
                .equals(response.getResponse().getParsedAuthenticatorData().getRpIdHash()),
457
            "Wrong RP ID hash.");
458
      } catch (IllegalArgumentException e) {
459
        Optional<AppId> appid =
460
            request.getPublicKeyCredentialRequestOptions().getExtensions().getAppid();
461 1 1. validate : negated conditional → KILLED
        if (appid.isPresent()) {
462 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
          assertTrue(
463
              Crypto.sha256(appid.get().getId())
464
                  .equals(response.getResponse().getParsedAuthenticatorData().getRpIdHash()),
465
              "Wrong RP ID hash.");
466
        } else {
467
          throw e;
468
        }
469
      }
470
    }
471
472
    @Override
473
    public Step16 nextStep() {
474 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step15::nextStep → KILLED
      return new Step16(username, credential);
475
    }
476
  }
477
478
  @Value
479
  class Step16 implements Step<C, Step17> {
480
    private final Optional<String> username;
481
    private final C credential;
482
483
    @Override
484
    public void validate() {
485 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
486
          response.getResponse().getParsedAuthenticatorData().getFlags().UP,
487
          "User Presence is required.");
488
    }
489
490
    @Override
491
    public Step17 nextStep() {
492 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step16::nextStep → KILLED
      return new Step17(username, credential);
493
    }
494
  }
495
496
  @Value
497
  class Step17 implements Step<C, PendingStep16> {
498
    private final Optional<String> username;
499
    private final C credential;
500
501
    @Override
502
    public void validate() {
503
      if (request
504
          .getPublicKeyCredentialRequestOptions()
505
          .getUserVerification()
506 1 1. validate : negated conditional → KILLED
          .equals(Optional.of(UserVerificationRequirement.REQUIRED))) {
507 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
        assertTrue(
508
            response.getResponse().getParsedAuthenticatorData().getFlags().UV,
509
            "User Verification is required.");
510
      }
511
    }
512
513
    @Override
514
    public PendingStep16 nextStep() {
515 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step17::nextStep → KILLED
      return new PendingStep16(username, credential);
516
    }
517
  }
518
519
  @Value
520
  // Step 16 in editor's draft as of 2022-11-09 https://w3c.github.io/webauthn/
521
  // TODO: Finalize this when spec matures
522
  class PendingStep16 implements Step<C, Step18> {
523
    private final Optional<String> username;
524
    private final C credential;
525
526
    @Override
527
    public void validate() {
528 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
529 1 1. validate : negated conditional → KILLED
          !credential.isBackupEligible().isPresent()
530
              || response.getResponse().getParsedAuthenticatorData().getFlags().BE
531 1 1. validate : negated conditional → KILLED
                  == credential.isBackupEligible().get(),
532
          "Backup eligibility must not change; Stored: BE=%s, received: BE=%s for credential: %s",
533
          credential.isBackupEligible(),
534
          response.getResponse().getParsedAuthenticatorData().getFlags().BE,
535
          credential.getCredentialId());
536
    }
537
538
    @Override
539
    public Step18 nextStep() {
540 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$PendingStep16::nextStep → KILLED
      return new Step18(username, credential);
541
    }
542
  }
543
544
  @Value
545
  class Step18 implements Step<C, Step19> {
546
    private final Optional<String> username;
547
    private final C credential;
548
549
    @Override
550
    public void validate() {}
551
552
    @Override
553
    public Step19 nextStep() {
554 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step18::nextStep → KILLED
      return new Step19(username, credential);
555
    }
556
  }
557
558
  @Value
559
  class Step19 implements Step<C, Step20> {
560
    private final Optional<String> username;
561
    private final C credential;
562
563
    @Override
564
    public void validate() {
565 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(clientDataJsonHash().size() == 32, "Failed to compute hash of client data");
566
    }
567
568
    @Override
569
    public Step20 nextStep() {
570 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step19::nextStep → KILLED
      return new Step20(username, credential, clientDataJsonHash());
571
    }
572
573
    public ByteArray clientDataJsonHash() {
574 1 1. clientDataJsonHash : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step19::clientDataJsonHash → KILLED
      return Crypto.sha256(response.getResponse().getClientDataJSON());
575
    }
576
  }
577
578
  @Value
579
  class Step20 implements Step<C, Step21> {
580
    private final Optional<String> username;
581
    private final C credential;
582
    private final ByteArray clientDataJsonHash;
583
584
    @Override
585
    public void validate() {
586
      final ByteArray cose = credential.getPublicKeyCose();
587
      final PublicKey key;
588
589
      try {
590
        key = WebAuthnCodecs.importCosePublicKey(cose);
591
      } catch (IOException | InvalidKeySpecException e) {
592
        throw new IllegalArgumentException(
593
            String.format(
594
                "Failed to decode public key: Credential ID: %s COSE: %s",
595
                credential.getCredentialId().getBase64Url(), cose.getBase64Url()),
596
            e);
597
      } catch (NoSuchAlgorithmException e) {
598
        throw new RuntimeException(e);
599
      }
600
601
      final COSEAlgorithmIdentifier alg =
602
          COSEAlgorithmIdentifier.fromPublicKey(cose)
603
              .orElseThrow(
604
                  () ->
605 1 1. lambda$validate$0 : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::lambda$validate$0 → NO_COVERAGE
                      new IllegalArgumentException(
606
                          String.format("Failed to decode \"alg\" from COSE key: %s", cose)));
607
608 1 1. validate : negated conditional → KILLED
      if (!Crypto.verifySignature(key, signedBytes(), response.getResponse().getSignature(), alg)) {
609
        throw new IllegalArgumentException("Invalid assertion signature.");
610
      }
611
    }
612
613
    @Override
614
    public Step21 nextStep() {
615 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::nextStep → KILLED
      return new Step21(username, credential);
616
    }
617
618
    public ByteArray signedBytes() {
619 1 1. signedBytes : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::signedBytes → KILLED
      return response.getResponse().getAuthenticatorData().concat(clientDataJsonHash);
620
    }
621
  }
622
623
  @Value
624
  class Step21 implements Step<C, Finished> {
625
    private final Optional<String> username;
626
    private final C credential;
627
    private final long assertionSignatureCount;
628
    private final long storedSignatureCountBefore;
629
630
    public Step21(Optional<String> username, C credential) {
631
      this.username = username;
632
      this.credential = credential;
633
      this.assertionSignatureCount =
634
          response.getResponse().getParsedAuthenticatorData().getSignatureCounter();
635
      this.storedSignatureCountBefore = credential.getSignatureCount();
636
    }
637
638
    @Override
639
    public void validate() throws InvalidSignatureCountException {
640 2 1. validate : negated conditional → KILLED
2. validate : negated conditional → KILLED
      if (validateSignatureCounter && !signatureCounterValid()) {
641
        throw new InvalidSignatureCountException(
642 1 1. validate : Replaced long addition with subtraction → KILLED
            response.getId(), storedSignatureCountBefore + 1, assertionSignatureCount);
643
      }
644
    }
645
646
    private boolean signatureCounterValid() {
647 5 1. signatureCounterValid : negated conditional → KILLED
2. signatureCounterValid : negated conditional → KILLED
3. signatureCounterValid : changed conditional boundary → KILLED
4. signatureCounterValid : replaced boolean return with true for com/yubico/webauthn/FinishAssertionSteps$Step21::signatureCounterValid → KILLED
5. signatureCounterValid : negated conditional → KILLED
      return (assertionSignatureCount == 0 && storedSignatureCountBefore == 0)
648
          || assertionSignatureCount > storedSignatureCountBefore;
649
    }
650
651
    @Override
652
    public Finished nextStep() {
653 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step21::nextStep → KILLED
      return new Finished(credential, username, assertionSignatureCount, signatureCounterValid());
654
    }
655
  }
656
657
  @Value
658
  class Finished implements Step<C, Finished> {
659
    private final C credential;
660
    private final Optional<String> username;
661
    private final long assertionSignatureCount;
662
    private final boolean signatureCounterValid;
663
664
    @Override
665
    public void validate() {
666
      /* No-op */
667
    }
668
669
    @Override
670
    public Finished nextStep() {
671 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Finished::nextStep → NO_COVERAGE
      return this;
672
    }
673
674
    @Override
675
    public Optional<AssertionResult> result() {
676 1 1. result : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Finished::result → KILLED
      return Optional.of(
677
          new AssertionResult(
678
              true,
679
              response,
680
              (RegisteredCredential) credential,
681
              username.get(),
682
              signatureCounterValid));
683
    }
684
685
    public Optional<AssertionResultV2<C>> resultV2() {
686 1 1. resultV2 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Finished::resultV2 → KILLED
      return Optional.of(
687
          new AssertionResultV2<C>(true, response, credential, signatureCounterValid));
688
    }
689
  }
690
}

Mutations

74

1.1
Location : fromV1
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::fromV1 → KILLED

104

1.1
Location : getUsernameForUserHandle
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps::getUsernameForUserHandle → KILLED

2.2
Location : lambda$getUsernameForUserHandle$0
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps::lambda$getUsernameForUserHandle$0 → KILLED

108

1.1
Location : begin
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::begin → KILLED

112

1.1
Location : run
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::run → KILLED

116

1.1
Location : runV2
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps::runV2 → KILLED

133

1.1
Location : next
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/webauthn/FinishAssertionSteps$Step::validate → KILLED

134

1.1
Location : next
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::next → KILLED

138

1.1
Location : run
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

139

1.1
Location : run
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::run → KILLED

141

1.1
Location : run
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::run → KILLED

146

1.1
Location : runV2
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

147

1.1
Location : runV2
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::runV2 → KILLED

149

1.1
Location : runV2
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step::runV2 → KILLED

160

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step5::nextStep → KILLED

168

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

2.2
Location : lambda$validate$0
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with true for com/yubico/webauthn/FinishAssertionSteps$Step5::lambda$validate$0 → KILLED

169

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

171

1.1
Location : lambda$validate$2
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

172

1.1
Location : lambda$validate$1
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced boolean return with false for com/yubico/webauthn/FinishAssertionSteps$Step5::lambda$validate$1 → KILLED

2.2
Location : lambda$validate$1
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with true for com/yubico/webauthn/FinishAssertionSteps$Step5::lambda$validate$1 → KILLED

203

1.1
Location : lambda$new$1
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$1 → KILLED

204

1.1
Location : lambda$new$0
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$0 → KILLED

210

1.1
Location : lambda$new$3
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$3 → KILLED

2.2
Location : lambda$new$2
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$2 → KILLED

213

1.1
Location : <init>
Killed by : none
negated conditional → SURVIVED

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

219

1.1
Location : lambda$new$5
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$5 → KILLED

2.2
Location : lambda$new$4
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$4 → KILLED

222

1.1
Location : lambda$new$6
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$6 → KILLED

227

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step6::nextStep → KILLED

232

1.1
Location : validate
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

233

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

2.2
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

236

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

238

1.1
Location : lambda$validate$7
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

241

1.1
Location : validate
Killed by : none
removed call to java/util/Optional::ifPresent → SURVIVED

243

1.1
Location : lambda$validate$8
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

244

1.1
Location : lambda$validate$8
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

249

1.1
Location : validate
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

253

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

254

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

258

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

260

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

263

1.1
Location : lambda$validate$10
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

267

1.1
Location : lambda$validate$10
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to java/util/Optional::ifPresent → KILLED

269

1.1
Location : lambda$validate$9
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

276

1.1
Location : lambda$validate$10
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

283

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

299

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step7::nextStep → KILLED

304

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

320

1.1
Location : validate
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

2.2
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

321

1.1
Location : validate
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

2.2
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

322

1.1
Location : validate
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

2.2
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

327

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::nextStep → KILLED

331

1.1
Location : authenticatorData
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::authenticatorData → KILLED

335

1.1
Location : clientData
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::clientData → KILLED

339

1.1
Location : signature
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::signature → KILLED

352

1.1
Location : validate
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

2.2
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

357

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step10::nextStep → KILLED

361

1.1
Location : clientData
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step10::clientData → KILLED

374

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

375

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

384

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step11::nextStep → KILLED

395

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

405

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step12::nextStep → KILLED

417

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

425

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step13::nextStep → KILLED

442

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step14::nextStep → KILLED

454

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

461

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

462

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

474

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step15::nextStep → KILLED

485

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

492

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step16::nextStep → KILLED

506

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

507

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

515

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step17::nextStep → KILLED

528

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

529

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

531

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

540

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$PendingStep16::nextStep → KILLED

554

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step18::nextStep → KILLED

565

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

2.2
Location : validate
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

570

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step19::nextStep → KILLED

574

1.1
Location : clientDataJsonHash
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step19::clientDataJsonHash → KILLED

605

1.1
Location : lambda$validate$0
Killed by : none
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::lambda$validate$0 → NO_COVERAGE

608

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

615

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::nextStep → KILLED

619

1.1
Location : signedBytes
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::signedBytes → KILLED

640

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

2.2
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

642

1.1
Location : validate
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
Replaced long addition with subtraction → KILLED

647

1.1
Location : signatureCounterValid
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
negated conditional → KILLED

2.2
Location : signatureCounterValid
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

3.3
Location : signatureCounterValid
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
changed conditional boundary → KILLED

4.4
Location : signatureCounterValid
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced boolean return with true for com/yubico/webauthn/FinishAssertionSteps$Step21::signatureCounterValid → KILLED

5.5
Location : signatureCounterValid
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
negated conditional → KILLED

653

1.1
Location : nextStep
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step21::nextStep → KILLED

671

1.1
Location : nextStep
Killed by : none
replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Finished::nextStep → NO_COVERAGE

676

1.1
Location : result
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Finished::result → KILLED

686

1.1
Location : resultV2
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Finished::resultV2 → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.0