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