| 1 | package com.yubico.fido.metadata; | |
| 2 | ||
| 3 | import com.fasterxml.jackson.annotation.JsonCreator; | |
| 4 | import com.fasterxml.jackson.annotation.JsonValue; | |
| 5 | import com.yubico.internal.util.BinaryUtil; | |
| 6 | import com.yubico.internal.util.ExceptionUtil; | |
| 7 | import com.yubico.webauthn.data.ByteArray; | |
| 8 | import java.util.regex.Matcher; | |
| 9 | import java.util.regex.Pattern; | |
| 10 | import lombok.AccessLevel; | |
| 11 | import lombok.Getter; | |
| 12 | import lombok.ToString; | |
| 13 | import lombok.Value; | |
| 14 | ||
| 15 | /** | |
| 16 | * Some authenticators have an AAGUID, which is a 128-bit identifier that indicates the type (e.g. | |
| 17 | * make and model) of the authenticator. The AAGUID MUST be chosen by the manufacturer to be | |
| 18 | * identical across all substantially identical authenticators made by that manufacturer, and | |
| 19 | * different (with probability 1-2-128 or greater) from the AAGUIDs of all other types of | |
| 20 | * authenticators. | |
| 21 | * | |
| 22 | * <p>The AAGUID is represented as a string (e.g. "7a98c250-6808-11cf-b73b-00aa00b677a7") consisting | |
| 23 | * of 5 hex strings separated by a dash ("-"), see [RFC4122]. | |
| 24 | * | |
| 25 | * @see <a | |
| 26 | * href="https://fidoalliance.org/specs/mds/fido-metadata-statement-v3.0-ps-20210518.html#typedefdef-aaguid">FIDO | |
| 27 | * Metadata Statement §3.1. Authenticator Attestation GUID (AAGUID) typedef</a> | |
| 28 | * @see <a href="https://tools.ietf.org/html/rfc4122">RFC 4122: A Universally Unique IDentifier | |
| 29 | * (UUID) URN Namespace</a> | |
| 30 | */ | |
| 31 | @Value | |
| 32 | @Getter(AccessLevel.NONE) | |
| 33 | @ToString(includeFieldNames = false, onlyExplicitlyIncluded = true) | |
| 34 | public class AAGUID { | |
| 35 | ||
| 36 | private static final Pattern AAGUID_PATTERN = | |
| 37 | Pattern.compile( | |
| 38 | "^([0-9a-fA-F]{8})-?([0-9a-fA-F]{4})-?([0-9a-fA-F]{4})-?([0-9a-fA-F]{4})-?([0-9a-fA-F]{12})$"); | |
| 39 | ||
| 40 | private static final ByteArray ZERO = | |
| 41 | new ByteArray(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); | |
| 42 | ||
| 43 | ByteArray value; | |
| 44 | ||
| 45 | /** | |
| 46 | * Construct an AAGUID from its raw binary representation. | |
| 47 | * | |
| 48 | * <p>This is the inverse of {@link #asBytes()}. | |
| 49 | * | |
| 50 | * @param value a {@link ByteArray} of length exactly 16. | |
| 51 | */ | |
| 52 | public AAGUID(ByteArray value) { | |
| 53 |
1
1. <init> : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → SURVIVED |
ExceptionUtil.assertTrue( |
| 54 |
1
1. <init> : negated conditional → KILLED |
value.size() == 16, |
| 55 | "AAGUID as bytes must be exactly 16 bytes long, was %d: %s", | |
| 56 | value.size(), | |
| 57 | value); | |
| 58 | this.value = value; | |
| 59 | } | |
| 60 | ||
| 61 | /** | |
| 62 | * The 16-byte binary representation of this AAGUID, for example <code> | |
| 63 | * 7a98c250680811cfb73b00aa00b677a7</code> when hex-encoded. | |
| 64 | * | |
| 65 | * <p>This is the inverse of {@link #AAGUID(ByteArray)}. | |
| 66 | */ | |
| 67 | public ByteArray asBytes() { | |
| 68 |
1
1. asBytes : replaced return value with null for com/yubico/fido/metadata/AAGUID::asBytes → KILLED |
return value; |
| 69 | } | |
| 70 | ||
| 71 | /** | |
| 72 | * The 32-character hexadecimal representation of this AAGUID, for example <code> | |
| 73 | * "7a98c250680811cfb73b00aa00b677a7"</code>. | |
| 74 | */ | |
| 75 | public String asHexString() { | |
| 76 |
1
1. asHexString : replaced return value with "" for com/yubico/fido/metadata/AAGUID::asHexString → KILLED |
return value.getHex(); |
| 77 | } | |
| 78 | ||
| 79 | /** | |
| 80 | * The 36-character string representation of this AAGUID, for example <code> | |
| 81 | * "7a98c250-6808-11cf-b73b-00aa00b677a7"</code>. | |
| 82 | */ | |
| 83 | @JsonValue | |
| 84 | @ToString.Include | |
| 85 | public String asGuidString() { | |
| 86 | final String hex = value.getHex(); | |
| 87 |
1
1. asGuidString : replaced return value with "" for com/yubico/fido/metadata/AAGUID::asGuidString → KILLED |
return String.format( |
| 88 | "%s-%s-%s-%s-%s", | |
| 89 | hex.substring(0, 8), | |
| 90 | hex.substring(8, 8 + 4), | |
| 91 | hex.substring(8 + 4, 8 + 4 + 4), | |
| 92 | hex.substring(8 + 4 + 4, 8 + 4 + 4 + 4), | |
| 93 | hex.substring(8 + 4 + 4 + 4, 8 + 4 + 4 + 4 + 12)); | |
| 94 | } | |
| 95 | ||
| 96 | /** | |
| 97 | * <code>true</code> if and only if this {@link AAGUID} consists of all zeroes. This typically | |
| 98 | * indicates that an authenticator has no AAGUID, or that the AAGUID has been redacted. | |
| 99 | */ | |
| 100 | public boolean isZero() { | |
| 101 |
2
1. isZero : replaced boolean return with true for com/yubico/fido/metadata/AAGUID::isZero → KILLED 2. isZero : replaced boolean return with false for com/yubico/fido/metadata/AAGUID::isZero → KILLED |
return ZERO.equals(value); |
| 102 | } | |
| 103 | ||
| 104 | private static ByteArray parse(String value) { | |
| 105 | Matcher matcher = AAGUID_PATTERN.matcher(value); | |
| 106 |
1
1. parse : negated conditional → KILLED |
if (matcher.find()) { |
| 107 | try { | |
| 108 |
1
1. parse : replaced return value with null for com/yubico/fido/metadata/AAGUID::parse → KILLED |
return new ByteArray( |
| 109 | BinaryUtil.concat( | |
| 110 | BinaryUtil.fromHex(matcher.group(1)), | |
| 111 | BinaryUtil.fromHex(matcher.group(2)), | |
| 112 | BinaryUtil.fromHex(matcher.group(3)), | |
| 113 | BinaryUtil.fromHex(matcher.group(4)), | |
| 114 | BinaryUtil.fromHex(matcher.group(5)))); | |
| 115 | } catch (Exception e) { | |
| 116 | throw new RuntimeException( | |
| 117 | "This exception should be impossible, please file a bug report.", e); | |
| 118 | } | |
| 119 | } else { | |
| 120 | throw new IllegalArgumentException("Value does not match AAGUID pattern: " + value); | |
| 121 | } | |
| 122 | } | |
| 123 | ||
| 124 | @JsonCreator | |
| 125 | private static AAGUID fromString(String aaguid) { | |
| 126 |
1
1. fromString : replaced return value with null for com/yubico/fido/metadata/AAGUID::fromString → KILLED |
return new AAGUID(parse(aaguid)); |
| 127 | } | |
| 128 | } | |
Mutations | ||
| 53 |
1.1 |
|
| 54 |
1.1 |
|
| 68 |
1.1 |
|
| 76 |
1.1 |
|
| 87 |
1.1 |
|
| 101 |
1.1 2.2 |
|
| 106 |
1.1 |
|
| 108 |
1.1 |
|
| 126 |
1.1 |