WebAuthnCodecs.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 com.google.common.primitives.Bytes;
28
import com.upokecenter.cbor.CBORObject;
29
import com.yubico.internal.util.BinaryUtil;
30
import com.yubico.webauthn.data.ByteArray;
31
import com.yubico.webauthn.data.COSEAlgorithmIdentifier;
32
import java.io.IOException;
33
import java.math.BigInteger;
34
import java.security.KeyFactory;
35
import java.security.NoSuchAlgorithmException;
36
import java.security.PublicKey;
37
import java.security.interfaces.ECPublicKey;
38
import java.security.spec.InvalidKeySpecException;
39
import java.security.spec.RSAPublicKeySpec;
40
import java.security.spec.X509EncodedKeySpec;
41
import java.util.Arrays;
42
import java.util.HashMap;
43
import java.util.Map;
44
45
final class WebAuthnCodecs {
46
47
  private static final ByteArray EC_PUBLIC_KEY_OID =
48
      new ByteArray(
49
          new byte[] {
50
            0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 2, 1
51
          }); // OID 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)
52
  private static final ByteArray P256_CURVE_OID =
53
      new ByteArray(
54
          new byte[] {
55
            0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 3, 1, 7 // OID 1.2.840.10045.3.1.7
56
          });
57
  private static final ByteArray P384_CURVE_OID =
58
      new ByteArray(new byte[] {0x2B, (byte) 0x81, 0x04, 0, 34}); // OID 1.3.132.0.34
59
  private static final ByteArray P521_CURVE_OID =
60
      new ByteArray(new byte[] {0x2B, (byte) 0x81, 0x04, 0, 35}); // OID 1.3.132.0.35
61
62
  static final ByteArray ED25519_ALG_ID =
63
      new ByteArray(
64
          new byte[] {
65
            // SEQUENCE (5 bytes)
66
            0x30,
67
            5,
68
            // OID (3 bytes)
69
            0x06,
70
            3,
71
            // OID 1.3.101.112
72
            0x2B,
73
            101,
74
            112
75
          });
76
77
  static final ByteArray ED448_ALG_ID =
78
      new ByteArray(
79
          new byte[] {
80
            // SEQUENCE (5 bytes)
81
            0x30,
82
            5,
83
            // OID (3 bytes)
84
            0x06,
85
            3,
86
            // OID 1.3.101.113
87
            0x2B,
88
            101,
89
            113
90
          });
91
92
  static final ByteArray ML_DSA_44_ALG_ID =
93
      new ByteArray(
94
          new byte[] {
95
            // SEQUENCE (11 bytes)
96
            0x30,
97
            0x0B,
98
            // OID (9 bytes)
99
            0x06,
100
            0x09,
101
            // OID 2.16.840.1.101.3.4.3.17
102
            0x60,
103
            (byte) 0x86,
104
            0x48,
105
            0x01,
106
            0x65,
107
            0x03,
108
            0x04,
109
            0x03,
110
            0x11
111
          });
112
113
  static final ByteArray ML_DSA_65_ALG_ID =
114
      new ByteArray(
115
          new byte[] {
116
            // SEQUENCE (11 bytes)
117
            0x30,
118
            0x0B,
119
            // OID (9 bytes)
120
            0x06,
121
            0x09,
122
            // OID 2.16.840.1.101.3.4.3.18
123
            0x60,
124
            (byte) 0x86,
125
            0x48,
126
            0x01,
127
            0x65,
128
            0x03,
129
            0x04,
130
            0x03,
131
            0x12
132
          });
133
134
  static final ByteArray ML_DSA_87_ALG_ID =
135
      new ByteArray(
136
          new byte[] {
137
            // SEQUENCE (11 bytes)
138
            0x30,
139
            0x0B,
140
            // OID (9 bytes)
141
            0x06,
142
            0x09,
143
            // OID 2.16.840.1.101.3.4.3.19
144
            0x60,
145
            (byte) 0x86,
146
            0x48,
147
            0x01,
148
            0x65,
149
            0x03,
150
            0x04,
151
            0x03,
152
            0x13
153
          });
154
155
  // See: https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
156
  static final int COSE_CRV_P256 = 1;
157
  static final int COSE_CRV_P384 = 2;
158
  static final int COSE_CRV_P521 = 3;
159
  static final int COSE_CRV_ED25519 = 6;
160
  static final int COSE_CRV_ED448 = 7;
161
162
  static ByteArray ecPublicKeyToRaw(ECPublicKey key) {
163
164
    final int fieldSizeBytes =
165
        Math.toIntExact(
166 1 1. ecPublicKeyToRaw : Replaced double division with multiplication → KILLED
            Math.round(Math.ceil(key.getParams().getCurve().getField().getFieldSize() / 8.0)));
167
    byte[] x = key.getW().getAffineX().toByteArray();
168
    byte[] y = key.getW().getAffineY().toByteArray();
169 1 1. ecPublicKeyToRaw : Replaced integer subtraction with addition → KILLED
    byte[] xPadding = new byte[Math.max(0, fieldSizeBytes - x.length)];
170 1 1. ecPublicKeyToRaw : Replaced integer subtraction with addition → KILLED
    byte[] yPadding = new byte[Math.max(0, fieldSizeBytes - y.length)];
171
172 1 1. ecPublicKeyToRaw : removed call to java/util/Arrays::fill → SURVIVED
    Arrays.fill(xPadding, (byte) 0);
173 1 1. ecPublicKeyToRaw : removed call to java/util/Arrays::fill → SURVIVED
    Arrays.fill(yPadding, (byte) 0);
174
175 2 1. ecPublicKeyToRaw : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::ecPublicKeyToRaw → KILLED
2. ecPublicKeyToRaw : Replaced integer subtraction with addition → KILLED
    return new ByteArray(
176
        Bytes.concat(
177
            new byte[] {0x04},
178
            xPadding,
179 1 1. ecPublicKeyToRaw : Replaced integer subtraction with addition → KILLED
            Arrays.copyOfRange(x, Math.max(0, x.length - fieldSizeBytes), x.length),
180
            yPadding,
181
            Arrays.copyOfRange(y, Math.max(0, y.length - fieldSizeBytes), y.length)));
182
  }
183
184
  static ByteArray rawEcKeyToCose(ByteArray key) {
185
    final byte[] keyBytes = key.getBytes();
186
    final int len = keyBytes.length;
187 1 1. rawEcKeyToCose : Replaced integer subtraction with addition → KILLED
    final int lenSub1 = keyBytes.length - 1;
188 7 1. rawEcKeyToCose : negated conditional → SURVIVED
2. rawEcKeyToCose : negated conditional → SURVIVED
3. rawEcKeyToCose : negated conditional → NO_COVERAGE
4. rawEcKeyToCose : negated conditional → SURVIVED
5. rawEcKeyToCose : negated conditional → KILLED
6. rawEcKeyToCose : negated conditional → KILLED
7. rawEcKeyToCose : negated conditional → KILLED
    if (!(len == 64
189
        || len == 96
190
        || len == 132
191
        || (keyBytes[0] == 0x04 && (lenSub1 == 64 || lenSub1 == 96 || lenSub1 == 132)))) {
192
      throw new IllegalArgumentException(
193
          String.format(
194
              "Raw key must be 64, 96 or 132 bytes long, or start with 0x04 and be 65, 97 or 133 bytes long; was %d bytes starting with %02x",
195
              keyBytes.length, keyBytes[0]));
196
    }
197 3 1. rawEcKeyToCose : negated conditional → KILLED
2. rawEcKeyToCose : negated conditional → KILLED
3. rawEcKeyToCose : negated conditional → KILLED
    final int start = (len == 64 || len == 96 || len == 132) ? 0 : 1;
198 2 1. rawEcKeyToCose : Replaced integer division with multiplication → KILLED
2. rawEcKeyToCose : Replaced integer subtraction with addition → KILLED
    final int coordinateLength = (len - start) / 2;
199
200
    final Map<Long, Object> coseKey = new HashMap<>();
201
    coseKey.put(1L, 2L); // Key type: EC
202
203
    final COSEAlgorithmIdentifier coseAlg;
204
    final int coseCrv;
205 1 1. rawEcKeyToCose : Replaced integer subtraction with addition → KILLED
    switch (len - start) {
206
      case 64:
207
        coseAlg = COSEAlgorithmIdentifier.ES256;
208
        coseCrv = COSE_CRV_P256;
209
        break;
210
      case 96:
211
        coseAlg = COSEAlgorithmIdentifier.ES384;
212
        coseCrv = COSE_CRV_P384;
213
        break;
214
      case 132:
215
        coseAlg = COSEAlgorithmIdentifier.ES512;
216
        coseCrv = COSE_CRV_P521;
217
        break;
218
      default:
219
        throw new RuntimeException(
220
            "Failed to determine COSE EC algorithm. This should not be possible, please file a bug report.");
221
    }
222
    coseKey.put(3L, coseAlg.getId());
223
    coseKey.put(-1L, coseCrv);
224
225 1 1. rawEcKeyToCose : Replaced integer addition with subtraction → KILLED
    coseKey.put(-2L, Arrays.copyOfRange(keyBytes, start, start + coordinateLength)); // x
226
    coseKey.put(
227 3 1. rawEcKeyToCose : Replaced integer addition with subtraction → KILLED
2. rawEcKeyToCose : Replaced integer addition with subtraction → KILLED
3. rawEcKeyToCose : Replaced integer multiplication with division → KILLED
        -3L,
228
        Arrays.copyOfRange(keyBytes, start + coordinateLength, start + 2 * coordinateLength)); // y
229
230 1 1. rawEcKeyToCose : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::rawEcKeyToCose → KILLED
    return new ByteArray(CBORObject.FromObject(coseKey).EncodeToBytes());
231
  }
232
233
  static PublicKey importCosePublicKey(ByteArray key)
234
      throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
235
    CBORObject cose = CBORObject.DecodeFromBytes(key.getBytes());
236
    final int kty = cose.get(CBORObject.FromObject(1)).AsInt32();
237
    switch (kty) {
238
      case 1:
239 1 1. importCosePublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED
        return importCoseEdDsaPublicKey(cose);
240
      case 2:
241 1 1. importCosePublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED
        return importCoseEcdsaPublicKey(cose);
242
      case 3:
243 1 1. importCosePublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED
        return importCoseRsaPublicKey(cose);
244
      case 7:
245 1 1. importCosePublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED
        return importCoseMlDsaPublicKey(cose);
246
      default:
247
        throw new IllegalArgumentException("Unsupported key type: " + kty);
248
    }
249
  }
250
251
  private static PublicKey importCoseRsaPublicKey(CBORObject cose)
252
      throws NoSuchAlgorithmException, InvalidKeySpecException {
253
    RSAPublicKeySpec spec =
254
        new RSAPublicKeySpec(
255
            new BigInteger(1, cose.get(CBORObject.FromObject(-1)).GetByteString()),
256
            new BigInteger(1, cose.get(CBORObject.FromObject(-2)).GetByteString()));
257 1 1. importCoseRsaPublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseRsaPublicKey → KILLED
    return KeyFactory.getInstance("RSA").generatePublic(spec);
258
  }
259
260
  private static PublicKey importCoseEcdsaPublicKey(CBORObject cose)
261
      throws NoSuchAlgorithmException, InvalidKeySpecException {
262
    final int crv = cose.get(CBORObject.FromObject(-1)).AsInt32Value();
263
    final byte[] x = cose.get(CBORObject.FromObject(-2)).GetByteString();
264
    final byte[] y = cose.get(CBORObject.FromObject(-3)).GetByteString();
265
266
    final byte[] curveOid;
267
    switch (crv) {
268
      case COSE_CRV_P256:
269
        curveOid = P256_CURVE_OID.getBytes();
270
        break;
271
272
      case COSE_CRV_P384:
273
        curveOid = P384_CURVE_OID.getBytes();
274
        break;
275
276
      case COSE_CRV_P521:
277
        curveOid = P521_CURVE_OID.getBytes();
278
        break;
279
280
      default:
281
        throw new IllegalArgumentException("Unknown COSE EC2 curve: " + crv);
282
    }
283
284
    final byte[] algId =
285
        BinaryUtil.encodeDerSequence(
286
            BinaryUtil.encodeDerObjectId(EC_PUBLIC_KEY_OID.getBytes()),
287
            BinaryUtil.encodeDerObjectId(curveOid));
288
289
    final byte[] rawKey =
290
        BinaryUtil.encodeDerBitStringWithZeroUnused(
291
            BinaryUtil.concat(
292
                new byte[] {0x04}, // Raw EC public key with x and y
293
                x,
294
                y));
295
296
    final byte[] x509Key = BinaryUtil.encodeDerSequence(algId, rawKey);
297
298
    KeyFactory kFact = KeyFactory.getInstance("EC");
299 1 1. importCoseEcdsaPublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseEcdsaPublicKey → KILLED
    return kFact.generatePublic(new X509EncodedKeySpec(x509Key));
300
  }
301
302
  private static PublicKey importCoseEdDsaPublicKey(CBORObject cose)
303
      throws InvalidKeySpecException, NoSuchAlgorithmException {
304
    final int alg = cose.get(CBORObject.FromObject(3)).AsInt32();
305
    final int curveId = cose.get(CBORObject.FromObject(-1)).AsInt32();
306
    final ByteArray algorithmOid = coseCurveToEddsaAlgorithmOid(curveId);
307
    final byte[] rawKey = cose.get(CBORObject.FromObject(-2)).GetByteString();
308
    final byte[] x509Key =
309
        BinaryUtil.encodeDerSequence(
310
            algorithmOid.getBytes(), BinaryUtil.encodeDerBitStringWithZeroUnused(rawKey));
311
312
    KeyFactory kFact =
313
        KeyFactory.getInstance(
314
            getJavaAlgorithmName(
315
                COSEAlgorithmIdentifier.fromId(alg)
316 1 1. lambda$importCoseEdDsaPublicKey$0 : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::lambda$importCoseEdDsaPublicKey$0 → NO_COVERAGE
                    .orElseThrow(() -> new IllegalArgumentException("Unknown algorithm: " + alg))));
317 1 1. importCoseEdDsaPublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseEdDsaPublicKey → KILLED
    return kFact.generatePublic(new X509EncodedKeySpec(x509Key));
318
  }
319
320
  private static ByteArray coseCurveToEddsaAlgorithmOid(int curveId) {
321
    switch (curveId) {
322
      case COSE_CRV_ED25519:
323 1 1. coseCurveToEddsaAlgorithmOid : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::coseCurveToEddsaAlgorithmOid → KILLED
        return ED25519_ALG_ID;
324
      case COSE_CRV_ED448:
325 1 1. coseCurveToEddsaAlgorithmOid : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::coseCurveToEddsaAlgorithmOid → KILLED
        return ED448_ALG_ID;
326
      default:
327
        throw new IllegalArgumentException("Unsupported EdDSA curve: " + curveId);
328
    }
329
  }
330
331
  private static PublicKey importCoseMlDsaPublicKey(CBORObject cose)
332
      throws InvalidKeySpecException, NoSuchAlgorithmException {
333
    final int alg = cose.get(CBORObject.FromObject(3)).AsInt32();
334
    final ByteArray algorithmId = mlDsaAlgorithmId(alg);
335
    final byte[] rawKey = cose.get(CBORObject.FromObject(-1)).GetByteString();
336
    final byte[] x509Key =
337
        BinaryUtil.encodeDerSequence(
338
            algorithmId.getBytes(), BinaryUtil.encodeDerBitStringWithZeroUnused(rawKey));
339
340
    KeyFactory kFact =
341
        KeyFactory.getInstance(
342
            getJavaAlgorithmName(
343
                COSEAlgorithmIdentifier.fromId(alg)
344 1 1. lambda$importCoseMlDsaPublicKey$1 : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::lambda$importCoseMlDsaPublicKey$1 → NO_COVERAGE
                    .orElseThrow(() -> new IllegalArgumentException("Unknown algorithm: " + alg))));
345 1 1. importCoseMlDsaPublicKey : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseMlDsaPublicKey → KILLED
    return kFact.generatePublic(new X509EncodedKeySpec(x509Key));
346
  }
347
348
  private static ByteArray mlDsaAlgorithmId(int alg) {
349
    switch (alg) {
350
      case -48:
351 1 1. mlDsaAlgorithmId : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::mlDsaAlgorithmId → KILLED
        return ML_DSA_44_ALG_ID;
352
      case -49:
353 1 1. mlDsaAlgorithmId : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::mlDsaAlgorithmId → KILLED
        return ML_DSA_65_ALG_ID;
354
      case -50:
355 1 1. mlDsaAlgorithmId : replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::mlDsaAlgorithmId → KILLED
        return ML_DSA_87_ALG_ID;
356
      default:
357
        throw new IllegalArgumentException("Unsupported ML-DSA algorithm: " + alg);
358
    }
359
  }
360
361
  static String getJavaAlgorithmName(COSEAlgorithmIdentifier alg) {
362
    switch (alg) {
363
      case EdDSA:
364
      case Ed25519:
365 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "Ed25519";
366
      case Ed448:
367 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "Ed448";
368
      case ES256:
369 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "SHA256withECDSA";
370
      case ES384:
371 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "SHA384withECDSA";
372
      case ES512:
373 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "SHA512withECDSA";
374
      case RS256:
375 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "SHA256withRSA";
376
      case RS384:
377 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "SHA384withRSA";
378
      case RS512:
379 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "SHA512withRSA";
380
      case RS1:
381 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "SHA1withRSA";
382
      case ML_DSA_44:
383 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "ML-DSA-44";
384
      case ML_DSA_65:
385 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "ML-DSA-65";
386
      case ML_DSA_87:
387 1 1. getJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED
        return "ML-DSA-87";
388
      default:
389
        throw new IllegalArgumentException("Unknown algorithm: " + alg);
390
    }
391
  }
392
393
  static String jwsAlgorithmNameToJavaAlgorithmName(String alg) {
394 1 1. jwsAlgorithmNameToJavaAlgorithmName : negated conditional → KILLED
    switch (alg) {
395
      case "RS256":
396 1 1. jwsAlgorithmNameToJavaAlgorithmName : replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::jwsAlgorithmNameToJavaAlgorithmName → KILLED
        return "SHA256withRSA";
397
    }
398
    throw new IllegalArgumentException("Unknown algorithm: " + alg);
399
  }
400
}

Mutations

166

1.1
Location : ecPublicKeyToRaw
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced double division with multiplication → KILLED

169

1.1
Location : ecPublicKeyToRaw
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer subtraction with addition → KILLED

170

1.1
Location : ecPublicKeyToRaw
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer subtraction with addition → KILLED

172

1.1
Location : ecPublicKeyToRaw
Killed by : none
removed call to java/util/Arrays::fill → SURVIVED
Covering tests

173

1.1
Location : ecPublicKeyToRaw
Killed by : none
removed call to java/util/Arrays::fill → SURVIVED
Covering tests

175

1.1
Location : ecPublicKeyToRaw
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::ecPublicKeyToRaw → KILLED

2.2
Location : ecPublicKeyToRaw
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer subtraction with addition → KILLED

179

1.1
Location : ecPublicKeyToRaw
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer subtraction with addition → KILLED

187

1.1
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer subtraction with addition → KILLED

188

1.1
Location : rawEcKeyToCose
Killed by : none
negated conditional → SURVIVED
Covering tests

2.2
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
negated conditional → KILLED

3.3
Location : rawEcKeyToCose
Killed by : none
negated conditional → SURVIVED Covering tests

4.4
Location : rawEcKeyToCose
Killed by : none
negated conditional → NO_COVERAGE

5.5
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.RelyingPartyV2RegistrationSpec
negated conditional → KILLED

6.6
Location : rawEcKeyToCose
Killed by : none
negated conditional → SURVIVED Covering tests

7.7
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
negated conditional → KILLED

197

1.1
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
negated conditional → KILLED

2.2
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
negated conditional → KILLED

3.3
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
negated conditional → KILLED

198

1.1
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer division with multiplication → KILLED

2.2
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
Replaced integer subtraction with addition → KILLED

205

1.1
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer subtraction with addition → KILLED

225

1.1
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer addition with subtraction → KILLED

227

1.1
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer addition with subtraction → KILLED

2.2
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer addition with subtraction → KILLED

3.3
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
Replaced integer multiplication with division → KILLED

230

1.1
Location : rawEcKeyToCose
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::rawEcKeyToCose → KILLED

239

1.1
Location : importCosePublicKey
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED

241

1.1
Location : importCosePublicKey
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED

243

1.1
Location : importCosePublicKey
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED

245

1.1
Location : importCosePublicKey
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCosePublicKey → KILLED

257

1.1
Location : importCoseRsaPublicKey
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseRsaPublicKey → KILLED

299

1.1
Location : importCoseEcdsaPublicKey
Killed by : com.yubico.webauthn.data.AuthenticatorDataSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseEcdsaPublicKey → KILLED

316

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

317

1.1
Location : importCoseEdDsaPublicKey
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseEdDsaPublicKey → KILLED

323

1.1
Location : coseCurveToEddsaAlgorithmOid
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::coseCurveToEddsaAlgorithmOid → KILLED

325

1.1
Location : coseCurveToEddsaAlgorithmOid
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::coseCurveToEddsaAlgorithmOid → KILLED

344

1.1
Location : lambda$importCoseMlDsaPublicKey$1
Killed by : none
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::lambda$importCoseMlDsaPublicKey$1 → NO_COVERAGE

345

1.1
Location : importCoseMlDsaPublicKey
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::importCoseMlDsaPublicKey → KILLED

351

1.1
Location : mlDsaAlgorithmId
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::mlDsaAlgorithmId → KILLED

353

1.1
Location : mlDsaAlgorithmId
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::mlDsaAlgorithmId → KILLED

355

1.1
Location : mlDsaAlgorithmId
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/WebAuthnCodecs::mlDsaAlgorithmId → KILLED

365

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

367

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

369

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

371

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyV2RegistrationSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

373

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyV2RegistrationSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

375

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

377

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyTest.defaultSettingsLogWarningIfSomeAlgorithmNotAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

379

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyV2RegistrationSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

381

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyV2AssertionSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

383

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

385

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

387

1.1
Location : getJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::getJavaAlgorithmName → KILLED

394

1.1
Location : jwsAlgorithmNameToJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyV2RegistrationSpec
negated conditional → KILLED

396

1.1
Location : jwsAlgorithmNameToJavaAlgorithmName
Killed by : com.yubico.webauthn.RelyingPartyV2RegistrationSpec
replaced return value with "" for com/yubico/webauthn/WebAuthnCodecs::jwsAlgorithmNameToJavaAlgorithmName → KILLED

Active mutators

Tests examined


Report generated by PIT 1.20.3