Coverage Report

Created: 2025-06-24 07:00

/src/boringssl/crypto/asn1/tasn_utl.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2000-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 <string.h>
19
20
#include <openssl/asn1t.h>
21
#include <openssl/err.h>
22
#include <openssl/mem.h>
23
#include <openssl/obj.h>
24
#include <openssl/pool.h>
25
26
#include "../internal.h"
27
#include "internal.h"
28
29
30
// Utility functions for manipulating fields and offsets
31
32
// Add 'offset' to 'addr'
33
51.2M
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
34
35
// Given an ASN1_ITEM CHOICE type return the selector value
36
1.91M
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
37
1.91M
  int *sel = reinterpret_cast<int *>(offset2ptr(*pval, it->utype));
38
1.91M
  return *sel;
39
1.91M
}
40
41
// Given an ASN1_ITEM CHOICE type set the selector value, return old value.
42
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
43
815k
                             const ASN1_ITEM *it) {
44
815k
  int *sel, ret;
45
815k
  sel = reinterpret_cast<int *>(offset2ptr(*pval, it->utype));
46
815k
  ret = *sel;
47
815k
  *sel = value;
48
815k
  return ret;
49
815k
}
50
51
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval,
52
8.39M
                                              const ASN1_ITEM *it) {
53
8.39M
  if (it->itype != ASN1_ITYPE_SEQUENCE) {
54
0
    return NULL;
55
0
  }
56
8.39M
  const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs);
57
8.39M
  if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) {
58
8.39M
    return NULL;
59
8.39M
  }
60
0
  return reinterpret_cast<CRYPTO_refcount_t *>(
61
0
      offset2ptr(*pval, aux->ref_offset));
62
8.39M
}
63
64
4.19M
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) {
65
4.19M
  CRYPTO_refcount_t *references = asn1_get_references(pval, it);
66
4.19M
  if (references != NULL) {
67
0
    *references = 1;
68
0
  }
69
4.19M
}
70
71
4.19M
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) {
72
4.19M
  CRYPTO_refcount_t *references = asn1_get_references(pval, it);
73
4.19M
  if (references != NULL) {
74
0
    return CRYPTO_refcount_dec_and_test_zero(references);
75
0
  }
76
4.19M
  return 1;
77
4.19M
}
78
79
16.1M
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) {
80
16.1M
  assert(it->itype == ASN1_ITYPE_SEQUENCE);
81
16.1M
  const ASN1_AUX *aux;
82
16.1M
  if (!pval || !*pval) {
83
0
    return NULL;
84
0
  }
85
16.1M
  aux = reinterpret_cast<const ASN1_AUX *>(it->funcs);
86
16.1M
  if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) {
87
15.4M
    return NULL;
88
15.4M
  }
89
725k
  return reinterpret_cast<ASN1_ENCODING *>(offset2ptr(*pval, aux->enc_offset));
90
16.1M
}
91
92
4.19M
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
93
4.19M
  ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
94
4.19M
  if (enc) {
95
236k
    enc->enc = NULL;
96
236k
    enc->len = 0;
97
236k
    enc->buf = NULL;
98
236k
  }
99
4.19M
}
100
101
4.19M
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
102
4.19M
  ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
103
4.19M
  if (enc) {
104
236k
    asn1_encoding_clear(enc);
105
236k
  }
106
4.19M
}
107
108
int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t in_len,
109
2.82M
                  const ASN1_ITEM *it, CRYPTO_BUFFER *buf) {
110
2.82M
  ASN1_ENCODING *enc;
111
2.82M
  enc = asn1_get_enc_ptr(pval, it);
112
2.82M
  if (!enc) {
113
2.62M
    return 1;
114
2.62M
  }
115
116
199k
  asn1_encoding_clear(enc);
117
199k
  if (buf != NULL) {
118
194k
    assert(CRYPTO_BUFFER_data(buf) <= in &&
119
194k
           in + in_len <= CRYPTO_BUFFER_data(buf) + CRYPTO_BUFFER_len(buf));
120
194k
    CRYPTO_BUFFER_up_ref(buf);
121
194k
    enc->buf = buf;
122
194k
    enc->enc = (uint8_t *)in;
123
194k
  } else {
124
5.44k
    enc->enc = reinterpret_cast<uint8_t *>(OPENSSL_memdup(in, in_len));
125
5.44k
    if (!enc->enc) {
126
0
      return 0;
127
0
    }
128
5.44k
  }
129
130
199k
  enc->len = in_len;
131
199k
  return 1;
132
199k
}
133
134
439k
void asn1_encoding_clear(ASN1_ENCODING *enc) {
135
439k
  if (enc->buf != NULL) {
136
194k
    CRYPTO_BUFFER_free(enc->buf);
137
244k
  } else {
138
244k
    OPENSSL_free(enc->enc);
139
244k
  }
140
439k
  enc->enc = NULL;
141
439k
  enc->len = 0;
142
439k
  enc->buf = NULL;
143
439k
}
144
145
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
146
4.95M
                     const ASN1_ITEM *it) {
147
4.95M
  ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
148
4.95M
  if (!enc || enc->len == 0) {
149
4.90M
    return 0;
150
4.90M
  }
151
46.8k
  if (out) {
152
23.4k
    OPENSSL_memcpy(*out, enc->enc, enc->len);
153
23.4k
    *out += enc->len;
154
23.4k
  }
155
46.8k
  if (len) {
156
46.8k
    *len = enc->len;
157
46.8k
  }
158
46.8k
  return 1;
159
4.95M
}
160
161
// Given an ASN1_TEMPLATE get a pointer to a field
162
47.7M
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
163
47.7M
  ASN1_VALUE **pvaltmp =
164
47.7M
      reinterpret_cast<ASN1_VALUE **>(offset2ptr(*pval, tt->offset));
165
  // NOTE for BOOLEAN types the field is just a plain int so we can't return
166
  // int **, so settle for (int *).
167
47.7M
  return pvaltmp;
168
47.7M
}
169
170
// Handle ANY DEFINED BY template, find the selector, look up the relevant
171
// ASN1_TEMPLATE in the table and return it.
172
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
173
32.8M
                                 int nullerr) {
174
32.8M
  const ASN1_ADB *adb;
175
32.8M
  const ASN1_ADB_TABLE *atbl;
176
32.8M
  ASN1_VALUE **sfld;
177
32.8M
  int i;
178
32.8M
  if (!(tt->flags & ASN1_TFLG_ADB_MASK)) {
179
32.8M
    return tt;
180
32.8M
  }
181
182
  // Else ANY DEFINED BY ... get the table
183
12.8k
  adb = ASN1_ADB_ptr(tt->item);
184
185
  // Get the selector field
186
12.8k
  sfld = reinterpret_cast<ASN1_VALUE **>(offset2ptr(*pval, adb->offset));
187
188
  // Check if NULL
189
12.8k
  int selector;
190
12.8k
  if (*sfld == NULL) {
191
1.62k
    if (!adb->null_tt) {
192
1.62k
      goto err;
193
1.62k
    }
194
0
    return adb->null_tt;
195
1.62k
  }
196
197
  // Convert type to a NID:
198
  // NB: don't check for NID_undef here because it
199
  // might be a legitimate value in the table
200
11.2k
  assert(tt->flags & ASN1_TFLG_ADB_OID);
201
11.2k
  selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
202
203
  // Try to find matching entry in table Maybe should check application types
204
  // first to allow application override? Might also be useful to have a flag
205
  // which indicates table is sorted and we can do a binary search. For now
206
  // stick to a linear search.
207
208
25.2k
  for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) {
209
20.8k
    if (atbl->value == selector) {
210
6.82k
      return &atbl->tt;
211
6.82k
    }
212
20.8k
  }
213
214
  // FIXME: need to search application table too
215
216
  // No match, return default type
217
4.38k
  if (!adb->default_tt) {
218
0
    goto err;
219
0
  }
220
4.38k
  return adb->default_tt;
221
222
1.62k
err:
223
  // FIXME: should log the value or OID of unsupported type
224
1.62k
  if (nullerr) {
225
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
226
0
  }
227
1.62k
  return NULL;
228
4.38k
}