AuthenticatorAttestationResponse.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.data;
26
27
import com.fasterxml.jackson.annotation.JsonCreator;
28
import com.fasterxml.jackson.annotation.JsonIgnore;
29
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
30
import com.fasterxml.jackson.annotation.JsonProperty;
31
import com.yubico.internal.util.CollectionUtil;
32
import com.yubico.webauthn.data.exception.Base64UrlException;
33
import java.io.IOException;
34
import java.util.Collections;
35
import java.util.Set;
36
import java.util.SortedSet;
37
import lombok.Builder;
38
import lombok.Getter;
39
import lombok.NonNull;
40
import lombok.Value;
41
42
/**
43
 * Represents the authenticator's response to a client's request for the creation of a new public
44
 * key credential. It contains information about the new credential that can be used to identify it
45
 * for later use, and metadata that can be used by the WebAuthn Relying Party to assess the
46
 * characteristics of the credential during registration.
47
 *
48
 * @see <a
49
 *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#authenticatorattestationresponse">§5.2.1.
50
 *     Information About Public Key Credential (interface AuthenticatorAttestationResponse) </a>
51
 */
52
@Value
53
@JsonIgnoreProperties({"publicKey", "publicKeyAlgorithm"})
54
public class AuthenticatorAttestationResponse implements AuthenticatorResponse {
55
56
  /**
57
   * Contains an attestation object, which is opaque to, and cryptographically protected against
58
   * tampering by, the client. The attestation object contains both authenticator data and an
59
   * attestation statement. The former contains the AAGUID, a unique credential ID, and the
60
   * credential public key. The contents of the attestation statement are determined by the
61
   * attestation statement format used by the authenticator. It also contains any additional
62
   * information that the Relying Party's server requires to validate the attestation statement, as
63
   * well as to decode and validate the authenticator data along with the JSON-serialized client
64
   * data. For more details, see <a
65
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4
66
   * Attestation</a>, <a
67
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-generating-an-attestation-object">§6.4.4
68
   * Generating an Attestation Object</a>, and <a
69
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#fig-attStructs">Figure 5</a>.
70
   */
71
  @NonNull private final ByteArray attestationObject;
72
73
  @NonNull
74
  @Getter(onMethod = @__({@Override}))
75
  private final ByteArray clientDataJSON;
76
77
  /**
78
   * The return value from the <code>AuthenticatorAttestationResponse.getTransports()</code> method.
79
   *
80
   * @see <a
81
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dom-authenticatorattestationresponse-gettransports">§5.2.1.
82
   *     Information About Public Key Credential (interface AuthenticatorAttestationResponse)</a>
83
   */
84
  private final SortedSet<AuthenticatorTransport> transports;
85
86
  /** The {@link #attestationObject} parsed as a domain object. */
87
  @NonNull
88
  @JsonIgnore
89
  @Getter(onMethod = @__({@JsonIgnore}))
90
  private final transient AttestationObject attestation;
91
92
  @NonNull
93
  @JsonIgnore
94
  @Getter(onMethod = @__({@Override}))
95
  private final transient CollectedClientData clientData;
96
97
  @Override
98
  @JsonIgnore
99
  public ByteArray getAuthenticatorData() {
100 1 1. getAuthenticatorData : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse::getAuthenticatorData → NO_COVERAGE
    return attestation.getAuthenticatorData().getBytes();
101
  }
102
103
  @Builder(toBuilder = true)
104
  @JsonCreator
105
  private AuthenticatorAttestationResponse(
106 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("attestationObject") ByteArray attestationObject,
107 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("clientDataJSON") ByteArray clientDataJSON,
108
      @JsonProperty("transports") Set<AuthenticatorTransport> transports)
109
      throws IOException, Base64UrlException {
110
    this.attestationObject = attestationObject;
111
    this.clientDataJSON = clientDataJSON;
112
    this.transports =
113 1 1. <init> : negated conditional → KILLED
        transports == null
114
            ? Collections.emptySortedSet()
115
            : CollectionUtil.immutableSortedSet(transports);
116
117
    attestation = new AttestationObject(attestationObject);
118
    this.clientData = new CollectedClientData(clientDataJSON);
119
  }
120
121
  // The default getter in AuthenticatorResponse re-parses the authenticator data on every
122
  // invocation. This "optimization" override has no measurable impact on performance, but it seems
123
  // rude to obviously waste cycles for nothing.
124
  @Override
125
  public AuthenticatorData getParsedAuthenticatorData() {
126 1 1. getParsedAuthenticatorData : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse::getParsedAuthenticatorData → KILLED
    return attestation.getAuthenticatorData();
127
  }
128
129
  public static AuthenticatorAttestationResponseBuilder.MandatoryStages builder() {
130 1 1. builder : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse::builder → KILLED
    return new AuthenticatorAttestationResponseBuilder.MandatoryStages();
131
  }
132
133
  public static class AuthenticatorAttestationResponseBuilder {
134
    public static class MandatoryStages {
135
      private final AuthenticatorAttestationResponseBuilder builder =
136
          new AuthenticatorAttestationResponseBuilder();
137
138
      /**
139
       * {@link AuthenticatorAttestationResponseBuilder#attestationObject(ByteArray)
140
       * attestationObject} is a required parameter.
141
       *
142
       * @see AuthenticatorAttestationResponseBuilder#attestationObject(ByteArray)
143
       */
144
      public Step2 attestationObject(ByteArray attestationObject) {
145
        builder.attestationObject(attestationObject);
146 1 1. attestationObject : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse$AuthenticatorAttestationResponseBuilder$MandatoryStages::attestationObject → KILLED
        return new Step2();
147
      }
148
149
      public class Step2 {
150
        /**
151
         * {@link AuthenticatorAttestationResponseBuilder#clientDataJSON(ByteArray) clientDataJSON}
152
         * is a required parameter.
153
         *
154
         * @see AuthenticatorAttestationResponseBuilder#clientDataJSON(ByteArray)
155
         */
156
        public AuthenticatorAttestationResponseBuilder clientDataJSON(ByteArray clientDataJSON) {
157 1 1. clientDataJSON : replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse$AuthenticatorAttestationResponseBuilder$MandatoryStages$Step2::clientDataJSON → KILLED
          return builder.clientDataJSON(clientDataJSON);
158
        }
159
      }
160
    }
161
  }
162
}

Mutations

100

1.1
Location : getAuthenticatorData
Killed by : none
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse::getAuthenticatorData → NO_COVERAGE

106

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

107

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

113

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

126

1.1
Location : getParsedAuthenticatorData
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse::getParsedAuthenticatorData → KILLED

130

1.1
Location : builder
Killed by : com.yubico.webauthn.data.AuthenticatorAttestationResponseSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse::builder → KILLED

146

1.1
Location : attestationObject
Killed by : com.yubico.webauthn.data.AuthenticatorAttestationResponseSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse$AuthenticatorAttestationResponseBuilder$MandatoryStages::attestationObject → KILLED

157

1.1
Location : clientDataJSON
Killed by : com.yubico.webauthn.data.AuthenticatorAttestationResponseSpec
replaced return value with null for com/yubico/webauthn/data/AuthenticatorAttestationResponse$AuthenticatorAttestationResponseBuilder$MandatoryStages$Step2::clientDataJSON → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.0