BinaryUtil.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.internal.util;
26
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.nio.ByteBuffer;
30
import java.nio.ByteOrder;
31
import java.util.ArrayList;
32
import java.util.Arrays;
33
import java.util.List;
34
import java.util.Optional;
35
import lombok.NonNull;
36
import lombok.ToString;
37
import lombok.Value;
38
39
public class BinaryUtil {
40
41
  public static byte[] copy(byte[] bytes) {
42 1 1. copy : replaced return value with null for com/yubico/internal/util/BinaryUtil::copy → NO_COVERAGE
    return Arrays.copyOf(bytes, bytes.length);
43
  }
44
45
  /**
46
   * Copy <code>src</code> into <code>dest</code> beginning at the offset <code>destFrom</code>,
47
   * then return the modified <code>dest</code>.
48
   */
49
  public static byte[] copyInto(byte[] src, byte[] dest, int destFrom) {
50 3 1. copyInto : Replaced integer subtraction with addition → SURVIVED
2. copyInto : negated conditional → KILLED
3. copyInto : changed conditional boundary → KILLED
    if (dest.length - destFrom < src.length) {
51
      throw new IllegalArgumentException("Source array will not fit in destination array");
52
    }
53 2 1. copyInto : negated conditional → KILLED
2. copyInto : changed conditional boundary → KILLED
    if (destFrom < 0) {
54
      throw new IllegalArgumentException("Invalid destination range");
55
    }
56
57 2 1. copyInto : negated conditional → KILLED
2. copyInto : changed conditional boundary → KILLED
    for (int i = 0; i < src.length; ++i) {
58 1 1. copyInto : Replaced integer addition with subtraction → KILLED
      dest[destFrom + i] = src[i];
59
    }
60
61 1 1. copyInto : replaced return value with null for com/yubico/internal/util/BinaryUtil::copyInto → SURVIVED
    return dest;
62
  }
63
64
  /** Return a new array containing the concatenation of the argument <code>arrays</code>. */
65
  public static byte[] concat(byte[]... arrays) {
66 1 1. lambda$concat$0 : replaced Integer return value with 0 for com/yubico/internal/util/BinaryUtil::lambda$concat$0 → KILLED
    final int len = Arrays.stream(arrays).map(a -> a.length).reduce(0, Integer::sum);
67
    byte[] result = new byte[len];
68
    int i = 0;
69
    for (byte[] src : arrays) {
70
      copyInto(src, result, i);
71 1 1. concat : Replaced integer addition with subtraction → KILLED
      i += src.length;
72
    }
73 1 1. concat : replaced return value with null for com/yubico/internal/util/BinaryUtil::concat → KILLED
    return result;
74
  }
75
76
  /**
77
   * @param bytes Bytes to encode
78
   */
79
  public static String toHex(final byte[] bytes) {
80 1 1. toHex : Replaced integer multiplication with division → KILLED
    final char[] digits = new char[bytes.length * 2];
81 2 1. toHex : negated conditional → KILLED
2. toHex : changed conditional boundary → KILLED
    for (int i = 0; i < bytes.length; ++i) {
82 1 1. toHex : Replaced integer multiplication with division → KILLED
      final int i2 = i * 2;
83 2 1. toHex : Replaced bitwise AND with OR → KILLED
2. toHex : Replaced Shift Right with Shift Left → KILLED
      digits[i2] = Character.forDigit((bytes[i] >> 4) & 0x0f, 16);
84 2 1. toHex : Replaced bitwise AND with OR → KILLED
2. toHex : Replaced integer addition with subtraction → KILLED
      digits[i2 + 1] = Character.forDigit(bytes[i] & 0x0f, 16);
85
    }
86 1 1. toHex : replaced return value with "" for com/yubico/internal/util/BinaryUtil::toHex → KILLED
    return new String(digits);
87
  }
88
89
  /**
90
   * @param hex String of hexadecimal digits to decode as bytes.
91
   */
92
  public static byte[] fromHex(final String hex) {
93 2 1. fromHex : negated conditional → KILLED
2. fromHex : Replaced integer modulus with multiplication → KILLED
    if (hex.length() % 2 != 0) {
94
      throw new IllegalArgumentException("Length of hex string is not even: " + hex);
95
    }
96
97 1 1. fromHex : Replaced integer division with multiplication → KILLED
    final byte[] result = new byte[hex.length() / 2];
98 2 1. fromHex : changed conditional boundary → KILLED
2. fromHex : negated conditional → KILLED
    for (int i = 0; i < hex.length(); ++i) {
99
      final int d = Character.digit(hex.charAt(i), 16);
100 2 1. fromHex : changed conditional boundary → KILLED
2. fromHex : negated conditional → KILLED
      if (d < 0) {
101
        throw new IllegalArgumentException("Invalid hex digit at index " + i + " in: " + hex);
102
      }
103 6 1. fromHex : Replaced integer addition with subtraction → KILLED
2. fromHex : Replaced integer division with multiplication → KILLED
3. fromHex : Replaced Shift Left with Shift Right → KILLED
4. fromHex : Replaced bitwise OR with AND → KILLED
5. fromHex : Replaced integer multiplication with division → KILLED
6. fromHex : Replaced integer modulus with multiplication → KILLED
      result[i / 2] |= d << (((i + 1) % 2) * 4);
104
    }
105 1 1. fromHex : replaced return value with null for com/yubico/internal/util/BinaryUtil::fromHex → KILLED
    return result;
106
  }
107
108
  /**
109
   * Parse a single byte from two hexadecimal characters.
110
   *
111
   * @param hex String of hexadecimal digits to decode as bytes.
112
   */
113
  public static byte singleFromHex(String hex) {
114 1 1. singleFromHex : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE
    ExceptionUtil.assertTrue(
115 1 1. singleFromHex : negated conditional → NO_COVERAGE
        hex.length() == 2, "Argument must be exactly 2 hexadecimal characters, was: %s", hex);
116 1 1. singleFromHex : replaced byte return with 0 for com/yubico/internal/util/BinaryUtil::singleFromHex → NO_COVERAGE
    return fromHex(hex)[0];
117
  }
118
119
  /**
120
   * Read one byte as an unsigned 8-bit integer.
121
   *
122
   * <p>Result is of type <code>short</code> because Java doesn't have unsigned types.
123
   *
124
   * @return A value between 0 and 255, inclusive.
125
   */
126
  public static short getUint8(byte b) {
127
    // Prepend a zero so we can parse it as a signed int16 instead of a signed int8
128 1 1. getUint8 : replaced short return with 0 for com/yubico/internal/util/BinaryUtil::getUint8 → KILLED
    return ByteBuffer.wrap(new byte[] {0, b}).order(ByteOrder.BIG_ENDIAN).getShort();
129
  }
130
131
  /**
132
   * Read 2 bytes as a big endian unsigned 16-bit integer.
133
   *
134
   * <p>Result is of type <code>int</code> because Java doesn't have unsigned types.
135
   *
136
   * @return A value between 0 and 2^16- 1, inclusive.
137
   */
138
  public static int getUint16(byte[] bytes) {
139 1 1. getUint16 : negated conditional → KILLED
    if (bytes.length == 2) {
140
      // Prepend zeroes so we can parse it as a signed int32 instead of a signed int16
141 1 1. getUint16 : replaced int return with 0 for com/yubico/internal/util/BinaryUtil::getUint16 → KILLED
      return ByteBuffer.wrap(new byte[] {0, 0, bytes[0], bytes[1]})
142
          .order(ByteOrder.BIG_ENDIAN)
143
          .getInt();
144
    } else {
145
      throw new IllegalArgumentException("Argument must be 2 bytes, was: " + bytes.length);
146
    }
147
  }
148
149
  /**
150
   * Read 4 bytes as a big endian unsigned 32-bit integer.
151
   *
152
   * <p>Result is of type <code>long</code> because Java doesn't have unsigned types.
153
   *
154
   * @return A value between 0 and 2^32 - 1, inclusive.
155
   */
156
  public static long getUint32(byte[] bytes) {
157 1 1. getUint32 : negated conditional → KILLED
    if (bytes.length == 4) {
158
      // Prepend zeroes so we can parse it as a signed int32 instead of a signed int16
159 1 1. getUint32 : replaced long return with 0 for com/yubico/internal/util/BinaryUtil::getUint32 → KILLED
      return ByteBuffer.wrap(new byte[] {0, 0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3]})
160
          .order(ByteOrder.BIG_ENDIAN)
161
          .getLong();
162
    } else {
163
      throw new IllegalArgumentException("Argument must be 4 bytes, was: " + bytes.length);
164
    }
165
  }
166
167
  public static byte[] encodeUint16(int value) {
168 3 1. encodeUint16 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
2. encodeUint16 : negated conditional → KILLED
3. encodeUint16 : changed conditional boundary → KILLED
    ExceptionUtil.assertTrue(value >= 0, "Argument must be non-negative, was: %d", value);
169 3 1. encodeUint16 : changed conditional boundary → SURVIVED
2. encodeUint16 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED
3. encodeUint16 : negated conditional → KILLED
    ExceptionUtil.assertTrue(
170
        value < 65536, "Argument must be smaller than 2^16=65536, was: %d", value);
171
172
    ByteBuffer b = ByteBuffer.allocate(4);
173
    b.order(ByteOrder.BIG_ENDIAN);
174
    b.putInt(value);
175
    b.rewind();
176 1 1. encodeUint16 : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint16 → KILLED
    return Arrays.copyOfRange(b.array(), 2, 4);
177
  }
178
179
  public static byte[] encodeUint32(long value) {
180 3 1. encodeUint32 : changed conditional boundary → NO_COVERAGE
2. encodeUint32 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE
3. encodeUint32 : negated conditional → NO_COVERAGE
    ExceptionUtil.assertTrue(value >= 0, "Argument must be non-negative, was: %d", value);
181 3 1. encodeUint32 : changed conditional boundary → NO_COVERAGE
2. encodeUint32 : removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE
3. encodeUint32 : negated conditional → NO_COVERAGE
    ExceptionUtil.assertTrue(
182
        value < 4294967296L, "Argument must be smaller than 2^32=4294967296, was: %d", value);
183
184
    ByteBuffer b = ByteBuffer.allocate(8);
185
    b.order(ByteOrder.BIG_ENDIAN);
186
    b.putLong(value);
187
    b.rewind();
188 1 1. encodeUint32 : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint32 → NO_COVERAGE
    return Arrays.copyOfRange(b.array(), 4, 8);
189
  }
190
191
  public static byte[] readAll(InputStream is) throws IOException {
192
    byte[] buffer = new byte[1024];
193
    int bufferLen = 0;
194
    while (true) {
195 1 1. readAll : Replaced integer subtraction with addition → NO_COVERAGE
      final int moreLen = is.read(buffer, bufferLen, buffer.length - bufferLen);
196 2 1. readAll : changed conditional boundary → NO_COVERAGE
2. readAll : negated conditional → NO_COVERAGE
      if (moreLen <= 0) {
197 1 1. readAll : replaced return value with null for com/yubico/internal/util/BinaryUtil::readAll → NO_COVERAGE
        return Arrays.copyOf(buffer, bufferLen);
198
      } else {
199 1 1. readAll : Replaced integer addition with subtraction → NO_COVERAGE
        bufferLen += moreLen;
200 1 1. readAll : negated conditional → NO_COVERAGE
        if (bufferLen == buffer.length) {
201 1 1. readAll : Replaced integer multiplication with division → NO_COVERAGE
          buffer = Arrays.copyOf(buffer, buffer.length * 2);
202
        }
203
      }
204
    }
205
  }
206
207
  public static byte[] encodeDerLength(final int length) {
208 2 1. encodeDerLength : negated conditional → KILLED
2. encodeDerLength : changed conditional boundary → KILLED
    if (length < 0) {
209
      throw new IllegalArgumentException("Length is negative: " + length);
210 2 1. encodeDerLength : changed conditional boundary → SURVIVED
2. encodeDerLength : negated conditional → KILLED
    } else if (length <= 0x7f) {
211 2 1. encodeDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → KILLED
2. encodeDerLength : Replaced bitwise AND with OR → KILLED
      return new byte[] {(byte) (length & 0xff)};
212 2 1. encodeDerLength : changed conditional boundary → SURVIVED
2. encodeDerLength : negated conditional → KILLED
    } else if (length <= 0xff) {
213 2 1. encodeDerLength : Replaced bitwise AND with OR → NO_COVERAGE
2. encodeDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → NO_COVERAGE
      return new byte[] {(byte) (0x80 | 0x01), (byte) (length & 0xff)};
214 2 1. encodeDerLength : changed conditional boundary → SURVIVED
2. encodeDerLength : negated conditional → KILLED
    } else if (length <= 0xffff) {
215 4 1. encodeDerLength : Replaced Shift Right with Shift Left → NO_COVERAGE
2. encodeDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → NO_COVERAGE
3. encodeDerLength : Replaced bitwise AND with OR → NO_COVERAGE
4. encodeDerLength : Replaced bitwise AND with OR → NO_COVERAGE
      return new byte[] {
216
        (byte) (0x80 | 0x02), (byte) ((length >> 8) & 0xff), (byte) (length & 0xff)
217
      };
218 2 1. encodeDerLength : changed conditional boundary → SURVIVED
2. encodeDerLength : negated conditional → KILLED
    } else if (length <= 0xffffff) {
219 6 1. encodeDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → NO_COVERAGE
2. encodeDerLength : Replaced bitwise AND with OR → NO_COVERAGE
3. encodeDerLength : Replaced bitwise AND with OR → NO_COVERAGE
4. encodeDerLength : Replaced Shift Right with Shift Left → NO_COVERAGE
5. encodeDerLength : Replaced bitwise AND with OR → NO_COVERAGE
6. encodeDerLength : Replaced Shift Right with Shift Left → NO_COVERAGE
      return new byte[] {
220
        (byte) (0x80 | 0x03),
221
        (byte) ((length >> 16) & 0xff),
222
        (byte) ((length >> 8) & 0xff),
223
        (byte) (length & 0xff)
224
      };
225
    } else {
226 8 1. encodeDerLength : Replaced bitwise AND with OR → KILLED
2. encodeDerLength : Replaced bitwise AND with OR → KILLED
3. encodeDerLength : Replaced Shift Right with Shift Left → KILLED
4. encodeDerLength : Replaced bitwise AND with OR → KILLED
5. encodeDerLength : Replaced bitwise AND with OR → KILLED
6. encodeDerLength : Replaced Shift Right with Shift Left → KILLED
7. encodeDerLength : Replaced Shift Right with Shift Left → KILLED
8. encodeDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → KILLED
      return new byte[] {
227
        (byte) (0x80 | 0x04),
228
        (byte) ((length >> 24) & 0xff),
229
        (byte) ((length >> 16) & 0xff),
230
        (byte) ((length >> 8) & 0xff),
231
        (byte) (length & 0xff)
232
      };
233
    }
234
  }
235
236
  @ToString
237
  public enum DerTagClass {
238
    UNIVERSAL,
239
    APPLICATION,
240
    CONTEXT_SPECIFIC,
241
    PRIVATE;
242
243
    public static DerTagClass parse(byte tag) {
244 2 1. parse : Replaced bitwise AND with OR → NO_COVERAGE
2. parse : Replaced Shift Right with Shift Left → NO_COVERAGE
      switch ((tag >> 6) & 0x03) {
245
        case 0x0:
246 1 1. parse : replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE
          return DerTagClass.UNIVERSAL;
247
        case 0x1:
248 1 1. parse : replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE
          return DerTagClass.APPLICATION;
249
        case 0x2:
250 1 1. parse : replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE
          return DerTagClass.CONTEXT_SPECIFIC;
251
        case 0x3:
252 1 1. parse : replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE
          return DerTagClass.PRIVATE;
253
        default:
254
          throw new RuntimeException("This should be impossible");
255
      }
256
    }
257
  }
258
259
  @Value
260
  private static class ParseDerAnyResult {
261
    DerTagClass tagClass;
262
    boolean constructed;
263
    byte tagValue;
264
    int valueStart;
265
    int valueEnd;
266
  }
267
268
  @Value
269
  public static class ParseDerResult<T> {
270
    /** The parsed value, excluding the tag-and-length header. */
271
    public T result;
272
273
    /**
274
     * The offset of the first octet past the end of the parsed value. In other words, the offset to
275
     * continue reading from.
276
     */
277
    public int nextOffset;
278
  }
279
280 1 1. parseDerLength : negated conditional → KILLED
  public static ParseDerResult<Integer> parseDerLength(@NonNull byte[] der, int offset) {
281 1 1. parseDerLength : Replaced integer subtraction with addition → SURVIVED
    final int len = der.length - offset;
282 1 1. parseDerLength : negated conditional → KILLED
    if (len == 0) {
283
      throw new IllegalArgumentException("Empty input");
284 2 1. parseDerLength : Replaced bitwise AND with OR → KILLED
2. parseDerLength : negated conditional → KILLED
    } else if ((der[offset] & 0x80) == 0) {
285 3 1. parseDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → SURVIVED
2. parseDerLength : Replaced bitwise AND with OR → KILLED
3. parseDerLength : Replaced integer addition with subtraction → KILLED
      return new ParseDerResult<>(der[offset] & 0xff, offset + 1);
286
    } else {
287 1 1. parseDerLength : Replaced bitwise AND with OR → KILLED
      final int longLen = der[offset] & 0x7f;
288 2 1. parseDerLength : changed conditional boundary → SURVIVED
2. parseDerLength : negated conditional → KILLED
      if (len >= longLen) {
289
        switch (longLen) {
290
          case 0:
291
            throw new IllegalArgumentException(
292
                String.format(
293
                    "Empty length encoding at offset %d: 0x%s", offset, BinaryUtil.toHex(der)));
294
          case 1:
295 4 1. parseDerLength : Replaced integer addition with subtraction → SURVIVED
2. parseDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED
3. parseDerLength : Replaced bitwise AND with OR → KILLED
4. parseDerLength : Replaced integer addition with subtraction → KILLED
            return new ParseDerResult<>(der[offset + 1] & 0xff, offset + 2);
296
          case 2:
297 7 1. parseDerLength : Replaced Shift Left with Shift Right → SURVIVED
2. parseDerLength : Replaced bitwise AND with OR → KILLED
3. parseDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED
4. parseDerLength : Replaced integer addition with subtraction → KILLED
5. parseDerLength : Replaced bitwise AND with OR → KILLED
6. parseDerLength : Replaced bitwise OR with AND → KILLED
7. parseDerLength : Replaced integer addition with subtraction → KILLED
            return new ParseDerResult<>(
298 1 1. parseDerLength : Replaced integer addition with subtraction → SURVIVED
                ((der[offset + 1] & 0xff) << 8) | (der[offset + 2] & 0xff), offset + 3);
299
          case 3:
300 11 1. parseDerLength : Replaced Shift Left with Shift Right → SURVIVED
2. parseDerLength : Replaced Shift Left with Shift Right → SURVIVED
3. parseDerLength : Replaced bitwise OR with AND → SURVIVED
4. parseDerLength : Replaced bitwise AND with OR → KILLED
5. parseDerLength : Replaced bitwise OR with AND → KILLED
6. parseDerLength : Replaced integer addition with subtraction → KILLED
7. parseDerLength : Replaced integer addition with subtraction → KILLED
8. parseDerLength : Replaced bitwise AND with OR → KILLED
9. parseDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED
10. parseDerLength : Replaced integer addition with subtraction → KILLED
11. parseDerLength : Replaced bitwise AND with OR → KILLED
            return new ParseDerResult<>(
301 1 1. parseDerLength : Replaced integer addition with subtraction → SURVIVED
                ((der[offset + 1] & 0xff) << 16)
302
                    | ((der[offset + 2] & 0xff) << 8)
303
                    | (der[offset + 3] & 0xff),
304
                offset + 4);
305
          case 4:
306 3 1. parseDerLength : Replaced integer addition with subtraction → KILLED
2. parseDerLength : negated conditional → KILLED
3. parseDerLength : Replaced bitwise AND with OR → KILLED
            if ((der[offset + 1] & 0x80) == 0) {
307 15 1. parseDerLength : Replaced bitwise AND with OR → KILLED
2. parseDerLength : Replaced integer addition with subtraction → KILLED
3. parseDerLength : Replaced bitwise AND with OR → KILLED
4. parseDerLength : Replaced Shift Left with Shift Right → KILLED
5. parseDerLength : Replaced Shift Left with Shift Right → KILLED
6. parseDerLength : Replaced bitwise AND with OR → KILLED
7. parseDerLength : Replaced bitwise OR with AND → KILLED
8. parseDerLength : Replaced bitwise OR with AND → KILLED
9. parseDerLength : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED
10. parseDerLength : Replaced integer addition with subtraction → KILLED
11. parseDerLength : Replaced integer addition with subtraction → KILLED
12. parseDerLength : Replaced bitwise AND with OR → KILLED
13. parseDerLength : Replaced Shift Left with Shift Right → KILLED
14. parseDerLength : Replaced bitwise OR with AND → KILLED
15. parseDerLength : Replaced integer addition with subtraction → KILLED
              return new ParseDerResult<>(
308 1 1. parseDerLength : Replaced integer addition with subtraction → KILLED
                  ((der[offset + 1] & 0xff) << 24)
309
                      | ((der[offset + 2] & 0xff) << 16)
310
                      | ((der[offset + 3] & 0xff) << 8)
311
                      | (der[offset + 4] & 0xff),
312
                  offset + 5);
313
            } else {
314 1 1. parseDerLength : Replaced integer addition with subtraction → NO_COVERAGE
              throw new UnsupportedOperationException(
315
                  String.format(
316
                      "Length out of range of int: 0x%02x%02x%02x%02x",
317 3 1. parseDerLength : Replaced integer addition with subtraction → NO_COVERAGE
2. parseDerLength : Replaced integer addition with subtraction → NO_COVERAGE
3. parseDerLength : Replaced integer addition with subtraction → NO_COVERAGE
                      der[offset + 1], der[offset + 2], der[offset + 3], der[offset + 4]));
318
            }
319
          default:
320
            throw new UnsupportedOperationException(
321
                String.format("Length is too long for int: %d octets", longLen));
322
        }
323
      } else {
324
        throw new IllegalArgumentException(
325
            String.format(
326
                "Length encoding needs %d octets but only %s remain at index %d: 0x%s",
327 3 1. parseDerLength : Replaced integer subtraction with addition → NO_COVERAGE
2. parseDerLength : Replaced integer addition with subtraction → NO_COVERAGE
3. parseDerLength : Replaced integer addition with subtraction → NO_COVERAGE
                longLen, len - (offset + 1), offset + 1, BinaryUtil.toHex(der)));
328
      }
329
    }
330
  }
331
332 1 1. parseDerAny : negated conditional → NO_COVERAGE
  private static ParseDerAnyResult parseDerAny(@NonNull byte[] der, int offset) {
333 1 1. parseDerAny : Replaced integer subtraction with addition → NO_COVERAGE
    final int len = der.length - offset;
334 1 1. parseDerAny : negated conditional → NO_COVERAGE
    if (len == 0) {
335
      throw new IllegalArgumentException(
336
          String.format("Empty input at offset %d: 0x%s", offset, BinaryUtil.toHex(der)));
337
    } else {
338
      final byte tag = der[offset];
339 1 1. parseDerAny : Replaced integer addition with subtraction → NO_COVERAGE
      final ParseDerResult<Integer> contentLen = parseDerLength(der, offset + 1);
340 1 1. parseDerAny : Replaced integer addition with subtraction → NO_COVERAGE
      final int contentEnd = contentLen.nextOffset + contentLen.result;
341 1 1. parseDerAny : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerAny → NO_COVERAGE
      return new ParseDerAnyResult(
342 3 1. parseDerAny : Replaced bitwise AND with OR → NO_COVERAGE
2. parseDerAny : Replaced bitwise AND with OR → NO_COVERAGE
3. parseDerAny : negated conditional → NO_COVERAGE
          DerTagClass.parse(tag),
343
          (tag & 0x20) != 0,
344
          (byte) (tag & 0x1f),
345
          contentLen.nextOffset,
346
          contentEnd);
347
    }
348
  }
349
350
  /**
351
   * Parse a DER header with the given tag value, constructed bit and tag class, and return the
352
   * start and end offsets of the value octets. If any of the three criteria do not match, return
353
   * empty instead.
354
   *
355
   * @param der DER source to read from.
356
   * @param offset The offset in <code>der</code> from which to start reading.
357
   * @param expectTag The expected tag value, excluding the constructed bit and tag class. This is
358
   *     the 5 least significant bits of the tag octet.
359
   * @param constructed The expected "constructed" bit. This is bit 6 (the third-most significant
360
   *     bit) of the tag octet.
361
   * @param expectTagClass The expected tag class. This is the 2 most significant bits of the tag
362
   *     octet.
363
   * @return The start and end offsets of the value octets, if the parsed tag matches <code>
364
   *     expectTag</code>, <code>
365
   *     constructed</code> and <code>expectTagClass</code>, otherwise empty. {@link
366
   *     ParseDerResult#nextOffset} is always returned.
367
   */
368
  public static ParseDerResult<Optional<Integer>> parseDerTaggedOrSkip(
369 1 1. parseDerTaggedOrSkip : negated conditional → NO_COVERAGE
      @NonNull byte[] der,
370
      int offset,
371
      byte expectTag,
372
      boolean constructed,
373
      DerTagClass expectTagClass) {
374
    final ParseDerAnyResult result = parseDerAny(der, offset);
375 1 1. parseDerTaggedOrSkip : negated conditional → NO_COVERAGE
    if (result.tagValue == expectTag
376 1 1. parseDerTaggedOrSkip : negated conditional → NO_COVERAGE
        && result.constructed == constructed
377 1 1. parseDerTaggedOrSkip : negated conditional → NO_COVERAGE
        && result.tagClass == expectTagClass) {
378 1 1. parseDerTaggedOrSkip : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerTaggedOrSkip → NO_COVERAGE
      return new ParseDerResult<>(Optional.of(result.valueStart), result.valueEnd);
379
    } else {
380 1 1. parseDerTaggedOrSkip : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerTaggedOrSkip → NO_COVERAGE
      return new ParseDerResult<>(Optional.empty(), result.valueEnd);
381
    }
382
  }
383
384
  /**
385
   * Parse a DER header with the given tag value, constructed bit and tag class, and return the
386
   * start and end offsets of the value octets. If any of the three criteria do not match, throw an
387
   * {@link IllegalArgumentException}.
388
   *
389
   * @param der DER source to read from.
390
   * @param offset The offset in <code>der</code> from which to start reading.
391
   * @param expectTag The expected tag value, excluding the constructed bit and tag class. This is
392
   *     the 5 least significant bits of the tag octet.
393
   * @param constructed The expected "constructed" bit. This is bit 6 (the third-most significant
394
   *     bit) of the tag octet.
395
   * @param expectTagClass The expected tag class. This is the 2 most significant bits of the tag
396
   *     octet.
397
   * @return The start and end offsets of the value octets, if the parsed tag matches <code>
398
   *     expectTag</code>, <code>
399
   *     constructed</code> and <code>expectTagClass</code>, otherwise empty. {@link
400
   *     ParseDerResult#nextOffset} is always returned.
401
   */
402
  private static ParseDerResult<Integer> parseDerTagged(
403 1 1. parseDerTagged : negated conditional → NO_COVERAGE
      @NonNull byte[] der,
404
      int offset,
405
      byte expectTag,
406
      boolean constructed,
407
      DerTagClass expectTagClass) {
408
    final ParseDerAnyResult result = parseDerAny(der, offset);
409 1 1. parseDerTagged : negated conditional → NO_COVERAGE
    if (result.tagValue == expectTag) {
410 1 1. parseDerTagged : negated conditional → NO_COVERAGE
      if (result.constructed == constructed) {
411 1 1. parseDerTagged : negated conditional → NO_COVERAGE
        if (result.tagClass == expectTagClass) {
412 1 1. parseDerTagged : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerTagged → NO_COVERAGE
          return new ParseDerResult<>(result.valueStart, result.valueEnd);
413
        } else {
414
          throw new IllegalArgumentException(
415
              String.format(
416
                  "Incorrect tag class: expected %s, found %s at offset %d: 0x%s",
417
                  expectTagClass, result.tagClass, offset, BinaryUtil.toHex(der)));
418
        }
419
      } else {
420
        throw new IllegalArgumentException(
421
            String.format(
422
                "Incorrect constructed bit: expected %s, found %s at offset %d: 0x%s",
423
                constructed, result.constructed, offset, BinaryUtil.toHex(der)));
424
      }
425
    } else {
426
      throw new IllegalArgumentException(
427
          String.format(
428
              "Incorrect tag: expected 0x%02x, found 0x%02x at offset %d: 0x%s",
429
              expectTag, result.tagValue, offset, BinaryUtil.toHex(der)));
430
    }
431
  }
432
433
  /** Function to parse an element of a DER SEQUENCE. */
434
  @FunctionalInterface
435
  public interface ParseDerSequenceElementFunction<T> {
436
    /**
437
     * Parse an element of a DER SEQUENCE.
438
     *
439
     * @param sequenceDer The content octets of the parent SEQUENCE. This includes ALL elements in
440
     *     the sequence.
441
     * @param elementOffset The offset into <code>sequenceDer</code> from where to parse the
442
     *     element.
443
     * @return A {@link ParseDerResult} whose {@link ParseDerResult#result} is the parsed element
444
     *     and {@link ParseDerResult#nextOffset} is the offset of the first octet past the end of
445
     *     the parsed element.
446
     */
447
    ParseDerResult<T> parse(@NonNull byte[] sequenceDer, int elementOffset);
448
  }
449
450
  /**
451
   * Parse the elements of a SEQUENCE using the given element parsing function.
452
   *
453
   * @param der DER source array to read from
454
   * @param offset Offset from which to begin reading the first element
455
   * @param endOffset Offset of the first octet past the end of the sequence
456
   * @param parseElement Function to use to parse each element in the sequence.
457
   */
458
  public static <T> ParseDerResult<List<T>> parseDerSequenceContents(
459 1 1. parseDerSequenceContents : negated conditional → NO_COVERAGE
      @NonNull byte[] der,
460
      int offset,
461
      int endOffset,
462 1 1. parseDerSequenceContents : negated conditional → NO_COVERAGE
      @NonNull ParseDerSequenceElementFunction<T> parseElement) {
463
    List<T> result = new ArrayList<>();
464
    int seqOffset = offset;
465 2 1. parseDerSequenceContents : changed conditional boundary → NO_COVERAGE
2. parseDerSequenceContents : negated conditional → NO_COVERAGE
    while (seqOffset < endOffset) {
466
      ParseDerResult<T> elementResult = parseElement.parse(der, seqOffset);
467
      result.add(elementResult.result);
468
      seqOffset = elementResult.nextOffset;
469
    }
470 1 1. parseDerSequenceContents : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerSequenceContents → NO_COVERAGE
    return new ParseDerResult<>(result, endOffset);
471
  }
472
473
  /**
474
   * Parse a SEQUENCE using the given element parsing function.
475
   *
476
   * @param der DER source array to read from
477
   * @param offset Offset from which to begin reading the SEQUENCE
478
   * @param parseElement Function to use to parse each element in the sequence.
479
   */
480
  public static <T> ParseDerResult<List<T>> parseDerSequence(
481 2 1. parseDerSequence : negated conditional → NO_COVERAGE
2. parseDerSequence : negated conditional → NO_COVERAGE
      @NonNull byte[] der, int offset, @NonNull ParseDerSequenceElementFunction<T> parseElement) {
482
    final ParseDerResult<Integer> seq =
483
        parseDerTagged(der, offset, (byte) 0x10, true, DerTagClass.UNIVERSAL);
484
    final ParseDerResult<List<T>> res =
485
        parseDerSequenceContents(der, seq.result, seq.nextOffset, parseElement);
486 1 1. parseDerSequence : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerSequence → NO_COVERAGE
    return new ParseDerResult<>(res.result, seq.nextOffset);
487
  }
488
489
  /** Parse an Octet String. */
490 1 1. parseDerOctetString : negated conditional → NO_COVERAGE
  public static ParseDerResult<byte[]> parseDerOctetString(@NonNull byte[] der, int offset) {
491
    ParseDerResult<Integer> res =
492
        parseDerTagged(der, offset, (byte) 0x04, false, DerTagClass.UNIVERSAL);
493 1 1. parseDerOctetString : replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerOctetString → NO_COVERAGE
    return new ParseDerResult<>(
494
        Arrays.copyOfRange(der, res.result, res.nextOffset), res.nextOffset);
495
  }
496
497 1 1. encodeDerObjectId : negated conditional → NO_COVERAGE
  public static byte[] encodeDerObjectId(@NonNull byte[] oid) {
498 1 1. encodeDerObjectId : Replaced integer addition with subtraction → NO_COVERAGE
    byte[] result = new byte[2 + oid.length];
499
    result[0] = 0x06;
500
    result[1] = (byte) oid.length;
501 1 1. encodeDerObjectId : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerObjectId → NO_COVERAGE
    return BinaryUtil.copyInto(oid, result, 2);
502
  }
503
504 1 1. encodeDerBitStringWithZeroUnused : negated conditional → NO_COVERAGE
  public static byte[] encodeDerBitStringWithZeroUnused(@NonNull byte[] content) {
505 2 1. encodeDerBitStringWithZeroUnused : Replaced integer addition with subtraction → NO_COVERAGE
2. encodeDerBitStringWithZeroUnused : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerBitStringWithZeroUnused → NO_COVERAGE
    return BinaryUtil.concat(
506
        new byte[] {0x03}, encodeDerLength(1 + content.length), new byte[] {0}, content);
507
  }
508
509
  public static byte[] encodeDerSequence(final byte[]... items) {
510
    byte[] content = BinaryUtil.concat(items);
511 1 1. encodeDerSequence : replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerSequence → NO_COVERAGE
    return BinaryUtil.concat(new byte[] {0x30}, encodeDerLength(content.length), content);
512
  }
513
}

Mutations

42

1.1
Location : copy
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::copy → NO_COVERAGE

50

1.1
Location : copyInto
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : copyInto
Killed by : none
Replaced integer subtraction with addition → SURVIVED

3.3
Location : copyInto
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

53

1.1
Location : copyInto
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : copyInto
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

57

1.1
Location : copyInto
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : copyInto
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

58

1.1
Location : copyInto
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

61

1.1
Location : copyInto
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::copyInto → SURVIVED

66

1.1
Location : lambda$concat$0
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced Integer return value with 0 for com/yubico/internal/util/BinaryUtil::lambda$concat$0 → KILLED

71

1.1
Location : concat
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

73

1.1
Location : concat
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::concat → KILLED

80

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced integer multiplication with division → KILLED

81

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
negated conditional → KILLED

2.2
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
changed conditional boundary → KILLED

82

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced integer multiplication with division → KILLED

83

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced bitwise AND with OR → KILLED

2.2
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced Shift Right with Shift Left → KILLED

84

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced bitwise AND with OR → KILLED

2.2
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
Replaced integer addition with subtraction → KILLED

86

1.1
Location : toHex
Killed by : com.yubico.internal.util.CertificateParserTest.subjectPublicKeyIdentifierIsCorrect(com.yubico.internal.util.CertificateParserTest)
replaced return value with "" for com/yubico/internal/util/BinaryUtil::toHex → KILLED

93

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer modulus with multiplication → KILLED

97

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer division with multiplication → KILLED

98

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

100

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

103

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

2.2
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer division with multiplication → KILLED

3.3
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Left with Shift Right → KILLED

4.4
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise OR with AND → KILLED

5.5
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer multiplication with division → KILLED

6.6
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer modulus with multiplication → KILLED

105

1.1
Location : fromHex
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::fromHex → KILLED

114

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

115

1.1
Location : singleFromHex
Killed by : none
negated conditional → NO_COVERAGE

116

1.1
Location : singleFromHex
Killed by : none
replaced byte return with 0 for com/yubico/internal/util/BinaryUtil::singleFromHex → NO_COVERAGE

128

1.1
Location : getUint8
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced short return with 0 for com/yubico/internal/util/BinaryUtil::getUint8 → KILLED

139

1.1
Location : getUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

141

1.1
Location : getUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced int return with 0 for com/yubico/internal/util/BinaryUtil::getUint16 → KILLED

157

1.1
Location : getUint32
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

159

1.1
Location : getUint32
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced long return with 0 for com/yubico/internal/util/BinaryUtil::getUint32 → KILLED

168

1.1
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

2.2
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

3.3
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

169

1.1
Location : encodeUint16
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → KILLED

3.3
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

176

1.1
Location : encodeUint16
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint16 → KILLED

180

1.1
Location : encodeUint32
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : encodeUint32
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE

3.3
Location : encodeUint32
Killed by : none
negated conditional → NO_COVERAGE

181

1.1
Location : encodeUint32
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : encodeUint32
Killed by : none
removed call to com/yubico/internal/util/ExceptionUtil::assertTrue → NO_COVERAGE

3.3
Location : encodeUint32
Killed by : none
negated conditional → NO_COVERAGE

188

1.1
Location : encodeUint32
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeUint32 → NO_COVERAGE

195

1.1
Location : readAll
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

196

1.1
Location : readAll
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : readAll
Killed by : none
negated conditional → NO_COVERAGE

197

1.1
Location : readAll
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::readAll → NO_COVERAGE

199

1.1
Location : readAll
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

200

1.1
Location : readAll
Killed by : none
negated conditional → NO_COVERAGE

201

1.1
Location : readAll
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

208

1.1
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
changed conditional boundary → KILLED

210

1.1
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : encodeDerLength
Killed by : none
changed conditional boundary → SURVIVED

211

1.1
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → KILLED

2.2
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

212

1.1
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

2.2
Location : encodeDerLength
Killed by : none
changed conditional boundary → SURVIVED

213

1.1
Location : encodeDerLength
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

2.2
Location : encodeDerLength
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → NO_COVERAGE

214

1.1
Location : encodeDerLength
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

215

1.1
Location : encodeDerLength
Killed by : none
Replaced Shift Right with Shift Left → NO_COVERAGE

2.2
Location : encodeDerLength
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → NO_COVERAGE

3.3
Location : encodeDerLength
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

4.4
Location : encodeDerLength
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

218

1.1
Location : encodeDerLength
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

219

1.1
Location : encodeDerLength
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → NO_COVERAGE

2.2
Location : encodeDerLength
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

3.3
Location : encodeDerLength
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

4.4
Location : encodeDerLength
Killed by : none
Replaced Shift Right with Shift Left → NO_COVERAGE

5.5
Location : encodeDerLength
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

6.6
Location : encodeDerLength
Killed by : none
Replaced Shift Right with Shift Left → NO_COVERAGE

226

1.1
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

2.2
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

3.3
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Right with Shift Left → KILLED

4.4
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

5.5
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

6.6
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Right with Shift Left → KILLED

7.7
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Right with Shift Left → KILLED

8.8
Location : encodeDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerLength → KILLED

244

1.1
Location : parse
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

2.2
Location : parse
Killed by : none
Replaced Shift Right with Shift Left → NO_COVERAGE

246

1.1
Location : parse
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE

248

1.1
Location : parse
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE

250

1.1
Location : parse
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE

252

1.1
Location : parse
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil$DerTagClass::parse → NO_COVERAGE

280

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

281

1.1
Location : parseDerLength
Killed by : none
Replaced integer subtraction with addition → SURVIVED

282

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

284

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

2.2
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

285

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

2.2
Location : parseDerLength
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → SURVIVED

3.3
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

287

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

288

1.1
Location : parseDerLength
Killed by : none
changed conditional boundary → SURVIVED

2.2
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

295

1.1
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → SURVIVED

2.2
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED

3.3
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

4.4
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

297

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

2.2
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED

3.3
Location : parseDerLength
Killed by : none
Replaced Shift Left with Shift Right → SURVIVED

4.4
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

5.5
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

6.6
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise OR with AND → KILLED

7.7
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

298

1.1
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → SURVIVED

300

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

2.2
Location : parseDerLength
Killed by : none
Replaced Shift Left with Shift Right → SURVIVED

3.3
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise OR with AND → KILLED

4.4
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

5.5
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

6.6
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

7.7
Location : parseDerLength
Killed by : none
Replaced Shift Left with Shift Right → SURVIVED

8.8
Location : parseDerLength
Killed by : none
Replaced bitwise OR with AND → SURVIVED

9.9
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED

10.10
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

11.11
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

301

1.1
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → SURVIVED

306

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

2.2
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
negated conditional → KILLED

3.3
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

307

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

2.2
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

3.3
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

4.4
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Left with Shift Right → KILLED

5.5
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Left with Shift Right → KILLED

6.6
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

7.7
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise OR with AND → KILLED

8.8
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise OR with AND → KILLED

9.9
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerLength → KILLED

10.10
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

11.11
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

12.12
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise AND with OR → KILLED

13.13
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced Shift Left with Shift Right → KILLED

14.14
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced bitwise OR with AND → KILLED

15.15
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

308

1.1
Location : parseDerLength
Killed by : com.yubico.internal.util.BinaryUtilSpec
Replaced integer addition with subtraction → KILLED

314

1.1
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

317

1.1
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

2.2
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

3.3
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

327

1.1
Location : parseDerLength
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

2.2
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

3.3
Location : parseDerLength
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

332

1.1
Location : parseDerAny
Killed by : none
negated conditional → NO_COVERAGE

333

1.1
Location : parseDerAny
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

334

1.1
Location : parseDerAny
Killed by : none
negated conditional → NO_COVERAGE

339

1.1
Location : parseDerAny
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

340

1.1
Location : parseDerAny
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

341

1.1
Location : parseDerAny
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerAny → NO_COVERAGE

342

1.1
Location : parseDerAny
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

2.2
Location : parseDerAny
Killed by : none
Replaced bitwise AND with OR → NO_COVERAGE

3.3
Location : parseDerAny
Killed by : none
negated conditional → NO_COVERAGE

369

1.1
Location : parseDerTaggedOrSkip
Killed by : none
negated conditional → NO_COVERAGE

375

1.1
Location : parseDerTaggedOrSkip
Killed by : none
negated conditional → NO_COVERAGE

376

1.1
Location : parseDerTaggedOrSkip
Killed by : none
negated conditional → NO_COVERAGE

377

1.1
Location : parseDerTaggedOrSkip
Killed by : none
negated conditional → NO_COVERAGE

378

1.1
Location : parseDerTaggedOrSkip
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerTaggedOrSkip → NO_COVERAGE

380

1.1
Location : parseDerTaggedOrSkip
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerTaggedOrSkip → NO_COVERAGE

403

1.1
Location : parseDerTagged
Killed by : none
negated conditional → NO_COVERAGE

409

1.1
Location : parseDerTagged
Killed by : none
negated conditional → NO_COVERAGE

410

1.1
Location : parseDerTagged
Killed by : none
negated conditional → NO_COVERAGE

411

1.1
Location : parseDerTagged
Killed by : none
negated conditional → NO_COVERAGE

412

1.1
Location : parseDerTagged
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerTagged → NO_COVERAGE

459

1.1
Location : parseDerSequenceContents
Killed by : none
negated conditional → NO_COVERAGE

462

1.1
Location : parseDerSequenceContents
Killed by : none
negated conditional → NO_COVERAGE

465

1.1
Location : parseDerSequenceContents
Killed by : none
changed conditional boundary → NO_COVERAGE

2.2
Location : parseDerSequenceContents
Killed by : none
negated conditional → NO_COVERAGE

470

1.1
Location : parseDerSequenceContents
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerSequenceContents → NO_COVERAGE

481

1.1
Location : parseDerSequence
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : parseDerSequence
Killed by : none
negated conditional → NO_COVERAGE

486

1.1
Location : parseDerSequence
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerSequence → NO_COVERAGE

490

1.1
Location : parseDerOctetString
Killed by : none
negated conditional → NO_COVERAGE

493

1.1
Location : parseDerOctetString
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::parseDerOctetString → NO_COVERAGE

497

1.1
Location : encodeDerObjectId
Killed by : none
negated conditional → NO_COVERAGE

498

1.1
Location : encodeDerObjectId
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

501

1.1
Location : encodeDerObjectId
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerObjectId → NO_COVERAGE

504

1.1
Location : encodeDerBitStringWithZeroUnused
Killed by : none
negated conditional → NO_COVERAGE

505

1.1
Location : encodeDerBitStringWithZeroUnused
Killed by : none
Replaced integer addition with subtraction → NO_COVERAGE

2.2
Location : encodeDerBitStringWithZeroUnused
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerBitStringWithZeroUnused → NO_COVERAGE

511

1.1
Location : encodeDerSequence
Killed by : none
replaced return value with null for com/yubico/internal/util/BinaryUtil::encodeDerSequence → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.15.0