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 → SURVIVED
2. lambda$new$2 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$2 → SURVIVED
                  requestedUserHandle.flatMap(FinishAssertionSteps.this::getUsernameForUserHandle));
211
212
      userHandleDerivedFromUsername =
213 2 1. <init> : negated conditional → KILLED
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 com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
      assertTrue(
237
          finalUserHandle.isPresent(),
238
          "Could not identify user to authenticate: none of requested username, requested user handle or response user handle are set.");
239
240 2 1. validate : negated conditional → KILLED
2. validate : negated conditional → KILLED
      if (requestedUserHandle.isPresent() && responseUserHandle.isPresent()) {
241 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
        assertTrue(
242
            requestedUserHandle.get().equals(responseUserHandle.get()),
243
            "User handle set in request (%s) does not match user handle in response (%s).",
244
            requestedUserHandle.get(),
245
            responseUserHandle.get());
246
      }
247
248 2 1. validate : negated conditional → KILLED
2. validate : negated conditional → KILLED
      if (userHandleDerivedFromUsername && responseUserHandle.isPresent()) {
249 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
        assertTrue(
250
            effectiveRequestUserHandle.get().equals(responseUserHandle.get()),
251
            "User handle in request (%s) (derived from username: %s) does not match user handle in response (%s).",
252
            effectiveRequestUserHandle.get(),
253
            requestedUsername.get(),
254
            responseUserHandle.get());
255
      }
256
257 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(registration.isPresent(), "Unknown credential: %s", response.getId());
258
259 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
260
          finalUserHandle.get().equals(registration.get().getUserHandle()),
261
          "User handle %s does not own credential %s",
262
          finalUserHandle.get(),
263
          response.getId());
264
265 1 1. validate : negated conditional → KILLED
      if (usernameRepository.isPresent()) {
266 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
        assertTrue(
267
            finalUsername.isPresent(),
268
            "Unknown username for user handle: %s",
269
            finalUserHandle.get());
270
      }
271
    }
272
  }
273
274
  @Value
275
  class Step7 implements Step<C, Step8> {
276
    private final Optional<String> username;
277
    private final ByteArray userHandle;
278
    private final Optional<C> credential;
279
280
    @Override
281
    public Step8 nextStep() {
282 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step7::nextStep → KILLED
      return new Step8(username, credential.get());
283
    }
284
285
    @Override
286
    public void validate() {
287 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
288
          credential.isPresent(),
289
          "Unknown credential. Credential ID: %s, user handle: %s",
290
          response.getId(),
291
          userHandle);
292
    }
293
  }
294
295
  @Value
296
  class Step8 implements Step<C, Step10> {
297
298
    private final Optional<String> username;
299
    private final C credential;
300
301
    @Override
302
    public void validate() {
303 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(clientData() != null, "Missing client data.");
304 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(authenticatorData() != null, "Missing authenticator data.");
305 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(signature() != null, "Missing signature.");
306
    }
307
308
    @Override
309
    public Step10 nextStep() {
310 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::nextStep → KILLED
      return new Step10(username, credential);
311
    }
312
313
    public ByteArray authenticatorData() {
314 1 1. authenticatorData : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::authenticatorData → KILLED
      return response.getResponse().getAuthenticatorData();
315
    }
316
317
    public ByteArray clientData() {
318 1 1. clientData : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::clientData → KILLED
      return response.getResponse().getClientDataJSON();
319
    }
320
321
    public ByteArray signature() {
322 1 1. signature : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step8::signature → KILLED
      return response.getResponse().getSignature();
323
    }
324
  }
325
326
  // Nothing to do for step 9
327
328
  @Value
329
  class Step10 implements Step<C, Step11> {
330
    private final Optional<String> username;
331
    private final C credential;
332
333
    @Override
334
    public void validate() {
335 2 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED
2. validate : negated conditional → KILLED
      assertTrue(clientData() != null, "Missing client data.");
336
    }
337
338
    @Override
339
    public Step11 nextStep() {
340 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step10::nextStep → KILLED
      return new Step11(username, credential, clientData());
341
    }
342
343
    public CollectedClientData clientData() {
344 1 1. clientData : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step10::clientData → KILLED
      return response.getResponse().getClientData();
345
    }
346
  }
347
348
  @Value
349
  class Step11 implements Step<C, Step12> {
350
    private final Optional<String> username;
351
    private final C credential;
352
    private final CollectedClientData clientData;
353
354
    @Override
355
    public void validate() {
356
      final String expectedType =
357 1 1. validate : negated conditional → KILLED
          isSecurePaymentConfirmation ? SPC_CLIENT_DATA_TYPE : CLIENT_DATA_TYPE;
358 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
359
          expectedType.equals(clientData.getType()),
360
          "The \"type\" in the client data must be exactly \"%s\", was: %s",
361
          expectedType,
362
          clientData.getType());
363
    }
364
365
    @Override
366
    public Step12 nextStep() {
367 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step11::nextStep → KILLED
      return new Step12(username, credential);
368
    }
369
  }
370
371
  @Value
372
  class Step12 implements Step<C, Step13> {
373
    private final Optional<String> username;
374
    private final C credential;
375
376
    @Override
377
    public void validate() {
378 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
379
          request
380
              .getPublicKeyCredentialRequestOptions()
381
              .getChallenge()
382
              .equals(response.getResponse().getClientData().getChallenge()),
383
          "Incorrect challenge.");
384
    }
385
386
    @Override
387
    public Step13 nextStep() {
388 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step12::nextStep → KILLED
      return new Step13(username, credential);
389
    }
390
  }
391
392
  @Value
393
  class Step13 implements Step<C, Step14> {
394
    private final Optional<String> username;
395
    private final C credential;
396
397
    @Override
398
    public void validate() {
399
      final String responseOrigin = response.getResponse().getClientData().getOrigin();
400 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
401
          OriginMatcher.isAllowed(responseOrigin, origins, allowOriginPort, allowOriginSubdomain),
402
          "Incorrect origin, please see the RelyingParty.origins setting: %s",
403
          responseOrigin);
404
    }
405
406
    @Override
407
    public Step14 nextStep() {
408 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step13::nextStep → KILLED
      return new Step14(username, credential);
409
    }
410
  }
411
412
  @Value
413
  class Step14 implements Step<C, Step15> {
414
    private final Optional<String> username;
415
    private final C credential;
416
417
    @Override
418
    public void validate() {
419
      TokenBindingValidator.validate(
420
          response.getResponse().getClientData().getTokenBinding(), callerTokenBindingId);
421
    }
422
423
    @Override
424
    public Step15 nextStep() {
425 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step14::nextStep → KILLED
      return new Step15(username, credential);
426
    }
427
  }
428
429
  @Value
430
  class Step15 implements Step<C, Step16> {
431
    private final Optional<String> username;
432
    private final C credential;
433
434
    @Override
435
    public void validate() {
436
      try {
437 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
        assertTrue(
438
            Crypto.sha256(rpId)
439
                .equals(response.getResponse().getParsedAuthenticatorData().getRpIdHash()),
440
            "Wrong RP ID hash.");
441
      } catch (IllegalArgumentException e) {
442
        Optional<AppId> appid =
443
            request.getPublicKeyCredentialRequestOptions().getExtensions().getAppid();
444 1 1. validate : negated conditional → KILLED
        if (appid.isPresent()) {
445 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
          assertTrue(
446
              Crypto.sha256(appid.get().getId())
447
                  .equals(response.getResponse().getParsedAuthenticatorData().getRpIdHash()),
448
              "Wrong RP ID hash.");
449
        } else {
450
          throw e;
451
        }
452
      }
453
    }
454
455
    @Override
456
    public Step16 nextStep() {
457 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step15::nextStep → KILLED
      return new Step16(username, credential);
458
    }
459
  }
460
461
  @Value
462
  class Step16 implements Step<C, Step17> {
463
    private final Optional<String> username;
464
    private final C credential;
465
466
    @Override
467
    public void validate() {
468 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
469
          response.getResponse().getParsedAuthenticatorData().getFlags().UP,
470
          "User Presence is required.");
471
    }
472
473
    @Override
474
    public Step17 nextStep() {
475 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step16::nextStep → KILLED
      return new Step17(username, credential);
476
    }
477
  }
478
479
  @Value
480
  class Step17 implements Step<C, PendingStep16> {
481
    private final Optional<String> username;
482
    private final C credential;
483
484
    @Override
485
    public void validate() {
486
      if (request
487
          .getPublicKeyCredentialRequestOptions()
488
          .getUserVerification()
489 1 1. validate : negated conditional → KILLED
          .equals(Optional.of(UserVerificationRequirement.REQUIRED))) {
490 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
        assertTrue(
491
            response.getResponse().getParsedAuthenticatorData().getFlags().UV,
492
            "User Verification is required.");
493
      }
494
    }
495
496
    @Override
497
    public PendingStep16 nextStep() {
498 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step17::nextStep → KILLED
      return new PendingStep16(username, credential);
499
    }
500
  }
501
502
  @Value
503
  // Step 16 in editor's draft as of 2022-11-09 https://w3c.github.io/webauthn/
504
  // TODO: Finalize this when spec matures
505
  class PendingStep16 implements Step<C, Step18> {
506
    private final Optional<String> username;
507
    private final C credential;
508
509
    @Override
510
    public void validate() {
511 1 1. validate : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
      assertTrue(
512 1 1. validate : negated conditional → KILLED
          !credential.isBackupEligible().isPresent()
513
              || response.getResponse().getParsedAuthenticatorData().getFlags().BE
514 1 1. validate : negated conditional → KILLED
                  == credential.isBackupEligible().get(),
515
          "Backup eligibility must not change; Stored: BE=%s, received: BE=%s for credential: %s",
516
          credential.isBackupEligible(),
517
          response.getResponse().getParsedAuthenticatorData().getFlags().BE,
518
          credential.getCredentialId());
519
    }
520
521
    @Override
522
    public Step18 nextStep() {
523 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$PendingStep16::nextStep → KILLED
      return new Step18(username, credential);
524
    }
525
  }
526
527
  @Value
528
  class Step18 implements Step<C, Step19> {
529
    private final Optional<String> username;
530
    private final C credential;
531
532
    @Override
533
    public void validate() {}
534
535
    @Override
536
    public Step19 nextStep() {
537 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step18::nextStep → KILLED
      return new Step19(username, credential);
538
    }
539
  }
540
541
  @Value
542
  class Step19 implements Step<C, Step20> {
543
    private final Optional<String> username;
544
    private final C credential;
545
546
    @Override
547
    public void validate() {
548 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");
549
    }
550
551
    @Override
552
    public Step20 nextStep() {
553 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step19::nextStep → KILLED
      return new Step20(username, credential, clientDataJsonHash());
554
    }
555
556
    public ByteArray clientDataJsonHash() {
557 1 1. clientDataJsonHash : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step19::clientDataJsonHash → KILLED
      return Crypto.sha256(response.getResponse().getClientDataJSON());
558
    }
559
  }
560
561
  @Value
562
  class Step20 implements Step<C, Step21> {
563
    private final Optional<String> username;
564
    private final C credential;
565
    private final ByteArray clientDataJsonHash;
566
567
    @Override
568
    public void validate() {
569
      final ByteArray cose = credential.getPublicKeyCose();
570
      final PublicKey key;
571
572
      try {
573
        key = WebAuthnCodecs.importCosePublicKey(cose);
574
      } catch (IOException | InvalidKeySpecException e) {
575
        throw new IllegalArgumentException(
576
            String.format(
577
                "Failed to decode public key: Credential ID: %s COSE: %s",
578
                credential.getCredentialId().getBase64Url(), cose.getBase64Url()),
579
            e);
580
      } catch (NoSuchAlgorithmException e) {
581
        throw new RuntimeException(e);
582
      }
583
584
      final COSEAlgorithmIdentifier alg =
585
          COSEAlgorithmIdentifier.fromPublicKey(cose)
586
              .orElseThrow(
587
                  () ->
588 1 1. lambda$validate$0 : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::lambda$validate$0 → NO_COVERAGE
                      new IllegalArgumentException(
589
                          String.format("Failed to decode \"alg\" from COSE key: %s", cose)));
590
591 1 1. validate : negated conditional → KILLED
      if (!Crypto.verifySignature(key, signedBytes(), response.getResponse().getSignature(), alg)) {
592
        throw new IllegalArgumentException("Invalid assertion signature.");
593
      }
594
    }
595
596
    @Override
597
    public Step21 nextStep() {
598 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::nextStep → KILLED
      return new Step21(username, credential);
599
    }
600
601
    public ByteArray signedBytes() {
602 1 1. signedBytes : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step20::signedBytes → KILLED
      return response.getResponse().getAuthenticatorData().concat(clientDataJsonHash);
603
    }
604
  }
605
606
  @Value
607
  class Step21 implements Step<C, Finished> {
608
    private final Optional<String> username;
609
    private final C credential;
610
    private final long assertionSignatureCount;
611
    private final long storedSignatureCountBefore;
612
613
    public Step21(Optional<String> username, C credential) {
614
      this.username = username;
615
      this.credential = credential;
616
      this.assertionSignatureCount =
617
          response.getResponse().getParsedAuthenticatorData().getSignatureCounter();
618
      this.storedSignatureCountBefore = credential.getSignatureCount();
619
    }
620
621
    @Override
622
    public void validate() throws InvalidSignatureCountException {
623 2 1. validate : negated conditional → KILLED
2. validate : negated conditional → KILLED
      if (validateSignatureCounter && !signatureCounterValid()) {
624
        throw new InvalidSignatureCountException(
625 1 1. validate : Replaced long addition with subtraction → KILLED
            response.getId(), storedSignatureCountBefore + 1, assertionSignatureCount);
626
      }
627
    }
628
629
    private boolean signatureCounterValid() {
630 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)
631
          || assertionSignatureCount > storedSignatureCountBefore;
632
    }
633
634
    @Override
635
    public Finished nextStep() {
636 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Step21::nextStep → KILLED
      return new Finished(credential, username, assertionSignatureCount, signatureCounterValid());
637
    }
638
  }
639
640
  @Value
641
  class Finished implements Step<C, Finished> {
642
    private final C credential;
643
    private final Optional<String> username;
644
    private final long assertionSignatureCount;
645
    private final boolean signatureCounterValid;
646
647
    @Override
648
    public void validate() {
649
      /* No-op */
650
    }
651
652
    @Override
653
    public Finished nextStep() {
654 1 1. nextStep : replaced return value with null for com/yubico/webauthn/FinishAssertionSteps$Finished::nextStep → NO_COVERAGE
      return this;
655
    }
656
657
    @Override
658
    public Optional<AssertionResult> result() {
659 1 1. result : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Finished::result → KILLED
      return Optional.of(
660
          new AssertionResult(
661
              true,
662
              response,
663
              (RegisteredCredential) credential,
664
              username.get(),
665
              signatureCounterValid));
666
    }
667
668
    public Optional<AssertionResultV2<C>> resultV2() {
669 1 1. resultV2 : replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Finished::resultV2 → KILLED
      return Optional.of(
670
          new AssertionResultV2<C>(true, response, credential, signatureCounterValid));
671
    }
672
  }
673
}

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 : none
replaced return value with Optional.empty for com/yubico/webauthn/FinishAssertionSteps$Step6::lambda$new$3 → SURVIVED

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

213

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

2.2
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
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 : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED

240

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

241

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

248

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

249

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

257

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

259

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

265

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

266

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

282

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

287

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

303

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

304

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

305

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

310

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

314

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

318

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

322

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

335

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

340

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

344

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

357

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

358

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

367

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

378

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

388

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

400

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

408

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

425

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

437

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

444

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

445

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

457

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

468

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

475

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

489

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

490

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

498

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

511

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

512

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

514

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

523

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

537

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

548

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

553

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

557

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

588

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

591

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

598

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

602

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

623

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

625

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

630

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

636

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

654

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

659

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

669

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