Coverage Report

Created: 2026-10-19 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/asn1/a_int.cc
Line
Count
Source
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/asn1.h>
16
17
#include <assert.h>
18
#include <limits.h>
19
#include <string.h>
20
21
#include <openssl/bytestring.h>
22
#include <openssl/err.h>
23
#include <openssl/mem.h>
24
#include <openssl/span.h>
25
26
#include "../internal.h"
27
#include "internal.h"
28
29
30
using namespace bssl;
31
32
64
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) {
33
64
  return ASN1_STRING_dup(x);
34
64
}
35
36
37
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) {
37
  // Compare signs.
38
37
  int neg = x->type & V_ASN1_NEG;
39
37
  if (neg != (y->type & V_ASN1_NEG)) {
40
2
    return neg ? -1 : 1;
41
2
  }
42
43
35
  int ret = ASN1_STRING_cmp(x, y);
44
35
  if (neg) {
45
    // This could be `-ret`, but `ASN1_STRING_cmp` is not forbidden from
46
    // returning `INT_MIN`.
47
17
    if (ret < 0) {
48
10
      return 1;
49
10
    } else if (ret > 0) {
50
6
      return -1;
51
6
    } else {
52
1
      return 0;
53
1
    }
54
17
  }
55
56
18
  return ret;
57
35
}
58
59
// negate_twos_complement negates `len` bytes from `buf` in-place, interpreted
60
// as a signed, big-endian two's complement value.
61
135k
static void negate_twos_complement(uint8_t *buf, size_t len) {
62
135k
  uint8_t borrow = 0;
63
6.70M
  for (size_t i = len - 1; i < len; i--) {
64
6.56M
    uint8_t t = buf[i];
65
6.56M
    buf[i] = 0u - borrow - t;
66
6.56M
    borrow |= t != 0;
67
6.56M
  }
68
135k
}
69
70
31.5k
static int is_all_zeros(const uint8_t *in, size_t len) {
71
70.3k
  for (size_t i = 0; i < len; i++) {
72
65.7k
    if (in[i] != 0) {
73
26.9k
      return 0;
74
26.9k
    }
75
65.7k
  }
76
4.60k
  return 1;
77
31.5k
}
78
79
int bssl::asn1_marshal_integer(CBB *out, const ASN1_INTEGER *in,
80
143k
                               CBS_ASN1_TAG tag) {
81
143k
  int len = i2c_ASN1_INTEGER(in, nullptr);
82
143k
  if (len <= 0) {
83
0
    return 0;
84
0
  }
85
143k
  tag = tag == 0 ? CBS_ASN1_INTEGER : tag;
86
143k
  CBB child;
87
143k
  uint8_t *ptr;
88
143k
  return CBB_add_asn1(out, &child, tag) &&     //
89
143k
         CBB_add_space(&child, &ptr, static_cast<size_t>(len)) &&   //
90
143k
         i2c_ASN1_INTEGER(in, &ptr) == len &&  //
91
143k
         CBB_flush(out);
92
143k
}
93
94
307k
int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) {
95
307k
  if (in == nullptr) {
96
0
    return 0;
97
0
  }
98
99
  // `ASN1_INTEGER`s should be represented minimally, but it is possible to
100
  // construct invalid ones. Skip leading zeros so this does not produce an
101
  // invalid encoding or break invariants.
102
307k
  CBS cbs;
103
307k
  CBS_init(&cbs, in->data, in->length);
104
307k
  while (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0) {
105
0
    CBS_skip(&cbs, 1);
106
0
  }
107
108
307k
  int is_negative = (in->type & V_ASN1_NEG) != 0;
109
307k
  size_t pad;
110
307k
  CBS copy = cbs;
111
307k
  uint8_t msb;
112
307k
  if (!CBS_get_u8(&copy, &msb)) {
113
    // Zero is represented as a single byte.
114
15.1k
    is_negative = 0;
115
15.1k
    pad = 1;
116
292k
  } else if (is_negative) {
117
    // 0x80...01 through 0xff...ff have a two's complement of 0x7f...ff
118
    // through 0x00...01 and need an extra byte to be negative.
119
    // 0x01...00 through 0x80...00 have a two's complement of 0xfe...ff
120
    // through 0x80...00 and can be negated as-is.
121
156k
    pad = msb > 0x80 ||
122
83.7k
          (msb == 0x80 && !is_all_zeros(CBS_data(&copy), CBS_len(&copy)));
123
156k
  } else {
124
    // If the high bit is set, the signed representation needs an extra
125
    // byte to be positive.
126
135k
    pad = (msb & 0x80) != 0;
127
135k
  }
128
129
307k
  if (CBS_len(&cbs) > INT_MAX - pad) {
130
0
    OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW);
131
0
    return 0;
132
0
  }
133
307k
  int len = (int)(pad + CBS_len(&cbs));
134
307k
  assert(len > 0);
135
307k
  if (outp == nullptr) {
136
153k
    return len;
137
153k
  }
138
139
153k
  if (pad) {
140
54.5k
    (*outp)[0] = 0;
141
54.5k
  }
142
153k
  OPENSSL_memcpy(*outp + pad, CBS_data(&cbs), CBS_len(&cbs));
143
153k
  if (is_negative) {
144
78.2k
    negate_twos_complement(*outp, len);
145
78.2k
    assert((*outp)[0] >= 0x80);
146
78.2k
  } else {
147
75.3k
    assert((*outp)[0] < 0x80);
148
75.3k
  }
149
153k
  *outp += len;
150
153k
  return len;
151
153k
}
152
153
static int asn1_parse_integer_contents(Span<const uint8_t> in,
154
293k
                                       ASN1_INTEGER *out) {
155
293k
  CBS cbs = in;
156
293k
  int is_negative;
157
293k
  if (!CBS_is_valid_asn1_integer(&cbs, &is_negative)) {
158
366
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER);
159
366
    return 0;
160
366
  }
161
162
  // Convert to `ASN1_INTEGER`'s sign-and-magnitude representation. First,
163
  // determine the size needed for a minimal result.
164
293k
  if (is_negative) {
165
    // 0xff00...01 through 0xff7f..ff have a two's complement of 0x00ff...ff
166
    // through 0x000100...001 and need one leading zero removed. 0x8000...00
167
    // through 0xff00...00 have a two's complement of 0x8000...00 through
168
    // 0x0100...00 and will be minimally-encoded as-is.
169
57.6k
    if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0xff &&
170
28.1k
        !is_all_zeros(CBS_data(&cbs) + 1, CBS_len(&cbs) - 1)) {
171
25.4k
      CBS_skip(&cbs, 1);
172
25.4k
    }
173
235k
  } else {
174
    // Remove the leading zero byte, if any.
175
235k
    if (CBS_len(&cbs) > 0 && CBS_data(&cbs)[0] == 0x00) {
176
143k
      CBS_skip(&cbs, 1);
177
143k
    }
178
235k
  }
179
180
293k
  if (!ASN1_STRING_set(out, CBS_data(&cbs), CBS_len(&cbs))) {
181
0
    return 0;
182
0
  }
183
184
293k
  if (is_negative) {
185
57.6k
    out->type = V_ASN1_NEG_INTEGER;
186
57.6k
    negate_twos_complement(out->data, out->length);
187
235k
  } else {
188
235k
    out->type = V_ASN1_INTEGER;
189
235k
  }
190
191
  // The value should be minimally-encoded.
192
293k
  assert(out->length == 0 || out->data[0] != 0);
193
  // Zero is not negative.
194
293k
  assert(!is_negative || out->length > 0);
195
293k
  return 1;
196
293k
}
197
198
295k
int bssl::asn1_parse_integer(CBS *cbs, ASN1_INTEGER *out, CBS_ASN1_TAG tag) {
199
295k
  tag = tag == 0 ? CBS_ASN1_INTEGER : tag;
200
295k
  CBS child;
201
295k
  if (!CBS_get_asn1(cbs, &child, tag)) {
202
2.09k
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
203
2.09k
    return 0;
204
2.09k
  }
205
293k
  return asn1_parse_integer_contents(child, out);
206
295k
}
207
208
int bssl::asn1_parse_enumerated(CBS *cbs, ASN1_ENUMERATED *out,
209
71.5k
                                CBS_ASN1_TAG tag) {
210
71.5k
  tag = tag == 0 ? CBS_ASN1_ENUMERATED : tag;
211
71.5k
  if (!asn1_parse_integer(cbs, out, tag)) {
212
889
    return 0;
213
889
  }
214
  // Fix the type value.
215
70.6k
  out->type =
216
70.6k
      (out->type & V_ASN1_NEG) ? V_ASN1_NEG_ENUMERATED : V_ASN1_ENUMERATED;
217
70.6k
  return 1;
218
71.5k
}
219
220
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp,
221
0
                               long len) {
222
0
  if (len < 0) {
223
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
224
0
    return nullptr;
225
0
  }
226
227
0
  ASN1_INTEGER *ret = nullptr;
228
0
  if (out == nullptr || *out == nullptr) {
229
0
    ret = ASN1_INTEGER_new();
230
0
    if (ret == nullptr) {
231
0
      return nullptr;
232
0
    }
233
0
  } else {
234
0
    ret = *out;
235
0
  }
236
237
0
  if (!asn1_parse_integer_contents(Span(*inp, len), ret)) {
238
0
    if (ret != nullptr && (out == nullptr || *out != ret)) {
239
0
      ASN1_INTEGER_free(ret);
240
0
    }
241
0
    return nullptr;
242
0
  }
243
244
0
  *inp += len;
245
0
  if (out != nullptr) {
246
0
    *out = ret;
247
0
  }
248
0
  return ret;
249
250
0
}
251
252
0
int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t v) {
253
0
  if (v >= 0) {
254
0
    return ASN1_INTEGER_set_uint64(a, (uint64_t)v);
255
0
  }
256
257
0
  if (!ASN1_INTEGER_set_uint64(a, 0 - (uint64_t)v)) {
258
0
    return 0;
259
0
  }
260
261
0
  a->type = V_ASN1_NEG_INTEGER;
262
0
  return 1;
263
0
}
264
265
0
int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t v) {
266
0
  if (v >= 0) {
267
0
    return ASN1_ENUMERATED_set_uint64(a, (uint64_t)v);
268
0
  }
269
270
0
  if (!ASN1_ENUMERATED_set_uint64(a, 0 - (uint64_t)v)) {
271
0
    return 0;
272
0
  }
273
274
0
  a->type = V_ASN1_NEG_ENUMERATED;
275
0
  return 1;
276
0
}
277
278
0
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) {
279
0
  static_assert(sizeof(long) <= sizeof(int64_t), "long fits in int64_t");
280
0
  return ASN1_INTEGER_set_int64(a, v);
281
0
}
282
283
0
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) {
284
0
  static_assert(sizeof(long) <= sizeof(int64_t), "long fits in int64_t");
285
0
  return ASN1_ENUMERATED_set_int64(a, v);
286
0
}
287
288
0
static int asn1_string_set_uint64(ASN1_STRING *out, uint64_t v, int type) {
289
0
  uint8_t buf[sizeof(uint64_t)];
290
0
  CRYPTO_store_u64_be(buf, v);
291
0
  size_t leading_zeros;
292
0
  for (leading_zeros = 0; leading_zeros < sizeof(buf); leading_zeros++) {
293
0
    if (buf[leading_zeros] != 0) {
294
0
      break;
295
0
    }
296
0
  }
297
298
0
  if (!ASN1_STRING_set(out, buf + leading_zeros, sizeof(buf) - leading_zeros)) {
299
0
    return 0;
300
0
  }
301
0
  out->type = type;
302
0
  return 1;
303
0
}
304
305
0
int ASN1_INTEGER_set_uint64(ASN1_INTEGER *out, uint64_t v) {
306
0
  return asn1_string_set_uint64(out, v, V_ASN1_INTEGER);
307
0
}
308
309
0
int ASN1_ENUMERATED_set_uint64(ASN1_ENUMERATED *out, uint64_t v) {
310
0
  return asn1_string_set_uint64(out, v, V_ASN1_ENUMERATED);
311
0
}
312
313
static int asn1_string_get_abs_uint64(uint64_t *out, const ASN1_STRING *a,
314
3.97k
                                      int type) {
315
3.97k
  if ((a->type & ~V_ASN1_NEG) != type) {
316
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE);
317
0
    return 0;
318
0
  }
319
3.97k
  uint8_t buf[sizeof(uint64_t)] = {0};
320
3.97k
  if (a->length > (int)sizeof(buf)) {
321
2.01k
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER);
322
2.01k
    return 0;
323
2.01k
  }
324
1.96k
  OPENSSL_memcpy(buf + sizeof(buf) - a->length, a->data, a->length);
325
1.96k
  *out = CRYPTO_load_u64_be(buf);
326
1.96k
  return 1;
327
3.97k
}
328
329
static int asn1_string_get_uint64(uint64_t *out, const ASN1_STRING *a,
330
2.88k
                                  int type) {
331
2.88k
  if (!asn1_string_get_abs_uint64(out, a, type)) {
332
1.67k
    return 0;
333
1.67k
  }
334
1.20k
  if (a->type & V_ASN1_NEG) {
335
394
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER);
336
394
    return 0;
337
394
  }
338
810
  return 1;
339
1.20k
}
340
341
2.88k
int ASN1_INTEGER_get_uint64(uint64_t *out, const ASN1_INTEGER *a) {
342
2.88k
  return asn1_string_get_uint64(out, a, V_ASN1_INTEGER);
343
2.88k
}
344
345
0
int ASN1_ENUMERATED_get_uint64(uint64_t *out, const ASN1_ENUMERATED *a) {
346
0
  return asn1_string_get_uint64(out, a, V_ASN1_ENUMERATED);
347
0
}
348
349
1.09k
static int asn1_string_get_int64(int64_t *out, const ASN1_STRING *a, int type) {
350
1.09k
  uint64_t v;
351
1.09k
  if (!asn1_string_get_abs_uint64(&v, a, type)) {
352
339
    return 0;
353
339
  }
354
758
  int64_t i64;
355
758
  int fits_in_i64;
356
  // Check `v != 0` to handle manually-constructed negative zeros.
357
758
  if ((a->type & V_ASN1_NEG) && v != 0) {
358
437
    i64 = (int64_t)(0u - v);
359
437
    fits_in_i64 = i64 < 0;
360
437
  } else {
361
321
    i64 = (int64_t)v;
362
321
    fits_in_i64 = i64 >= 0;
363
321
  }
364
758
  if (!fits_in_i64) {
365
228
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER);
366
228
    return 0;
367
228
  }
368
530
  *out = i64;
369
530
  return 1;
370
758
}
371
372
0
int ASN1_INTEGER_get_int64(int64_t *out, const ASN1_INTEGER *a) {
373
0
  return asn1_string_get_int64(out, a, V_ASN1_INTEGER);
374
0
}
375
376
0
int ASN1_ENUMERATED_get_int64(int64_t *out, const ASN1_ENUMERATED *a) {
377
0
  return asn1_string_get_int64(out, a, V_ASN1_ENUMERATED);
378
0
}
379
380
1.09k
static long asn1_string_get_long(const ASN1_STRING *a, int type) {
381
1.09k
  if (a == nullptr) {
382
0
    return 0;
383
0
  }
384
385
1.09k
  int64_t v;
386
1.09k
  if (!asn1_string_get_int64(&v, a, type) ||  //
387
567
      v < LONG_MIN || v > LONG_MAX) {
388
    // This function's return value does not distinguish overflow from -1.
389
567
    ERR_clear_error();
390
567
    return -1;
391
567
  }
392
393
530
  return (long)v;
394
1.09k
}
395
396
17
long ASN1_INTEGER_get(const ASN1_INTEGER *a) {
397
17
  return asn1_string_get_long(a, V_ASN1_INTEGER);
398
17
}
399
400
1.08k
long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a) {
401
1.08k
  return asn1_string_get_long(a, V_ASN1_ENUMERATED);
402
1.08k
}
403
404
static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai,
405
12.3k
                                      int type) {
406
12.3k
  ASN1_INTEGER *ret;
407
12.3k
  if (ai == nullptr) {
408
12.3k
    ret = ASN1_STRING_type_new(type);
409
12.3k
  } else {
410
0
    ret = ai;
411
0
  }
412
12.3k
  int len;
413
12.3k
  if (ret == nullptr) {
414
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
415
0
    goto err;
416
0
  }
417
418
12.3k
  if (BN_is_negative(bn) && !BN_is_zero(bn)) {
419
517
    ret->type = type | V_ASN1_NEG;
420
11.8k
  } else {
421
11.8k
    ret->type = type;
422
11.8k
  }
423
424
12.3k
  len = BN_num_bytes(bn);
425
12.3k
  if (!ASN1_STRING_set(ret, nullptr, len) ||
426
12.3k
      !BN_bn2bin_padded(ret->data, len, bn)) {
427
0
    goto err;
428
0
  }
429
12.3k
  return ret;
430
431
0
err:
432
0
  if (ret != ai) {
433
0
    ASN1_STRING_free(ret);
434
0
  }
435
0
  return nullptr;
436
12.3k
}
437
438
12.3k
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) {
439
12.3k
  return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER);
440
12.3k
}
441
442
0
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai) {
443
0
  return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED);
444
0
}
445
446
2.03k
static BIGNUM *asn1_string_to_bn(const ASN1_STRING *ai, BIGNUM *bn, int type) {
447
2.03k
  if ((ai->type & ~V_ASN1_NEG) != type) {
448
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_INTEGER_TYPE);
449
0
    return nullptr;
450
0
  }
451
452
2.03k
  BIGNUM *ret;
453
2.03k
  if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == nullptr) {
454
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
455
2.03k
  } else if (ai->type & V_ASN1_NEG) {
456
1.20k
    BN_set_negative(ret, 1);
457
1.20k
  }
458
2.03k
  return ret;
459
2.03k
}
460
461
1.00k
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) {
462
1.00k
  return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER);
463
1.00k
}
464
465
1.02k
BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn) {
466
1.02k
  return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED);
467
1.02k
}