Coverage Report

Created: 2025-06-11 06:41

/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
50.8M
#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
34
35
// Given an ASN1_ITEM CHOICE type return the selector value
36
1.85M
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
37
1.85M
  int *sel = reinterpret_cast<int *>(offset2ptr(*pval, it->utype));
38
1.85M
  return *sel;
39
1.85M
}
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
835k
                             const ASN1_ITEM *it) {
44
835k
  int *sel, ret;
45
835k
  sel = reinterpret_cast<int *>(offset2ptr(*pval, it->utype));
46
835k
  ret = *sel;
47
835k
  *sel = value;
48
835k
  return ret;
49
835k
}
50
51
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval,
52
8.34M
                                              const ASN1_ITEM *it) {
53
8.34M
  if (it->itype != ASN1_ITYPE_SEQUENCE) {
54
0
    return NULL;
55
0
  }
56
8.34M
  const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs);
57
8.34M
  if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) {
58
8.34M
    return NULL;
59
8.34M
  }
60
0
  return reinterpret_cast<CRYPTO_refcount_t *>(
61
0
      offset2ptr(*pval, aux->ref_offset));
62
8.34M
}
63
64
4.17M
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) {
65
4.17M
  CRYPTO_refcount_t *references = asn1_get_references(pval, it);
66
4.17M
  if (references != NULL) {
67
0
    *references = 1;
68
0
  }
69
4.17M
}
70
71
4.17M
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) {
72
4.17M
  CRYPTO_refcount_t *references = asn1_get_references(pval, it);
73
4.17M
  if (references != NULL) {
74
0
    return CRYPTO_refcount_dec_and_test_zero(references);
75
0
  }
76
4.17M
  return 1;
77
4.17M
}
78
79
16.0M
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) {
80
16.0M
  assert(it->itype == ASN1_ITYPE_SEQUENCE);
81
16.0M
  const ASN1_AUX *aux;
82
16.0M
  if (!pval || !*pval) {
83
0
    return NULL;
84
0
  }
85
16.0M
  aux = reinterpret_cast<const ASN1_AUX *>(it->funcs);
86
16.0M
  if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) {
87
15.3M
    return NULL;
88
15.3M
  }
89
719k
  return reinterpret_cast<ASN1_ENCODING *>(offset2ptr(*pval, aux->enc_offset));
90
16.0M
}
91
92
4.17M
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
93
4.17M
  ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
94
4.17M
  if (enc) {
95
234k
    enc->enc = NULL;
96
234k
    enc->len = 0;
97
234k
    enc->buf = NULL;
98
234k
  }
99
4.17M
}
100
101
4.17M
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
102
4.17M
  ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
103
4.17M
  if (enc) {
104
234k
    asn1_encoding_clear(enc);
105
234k
  }
106
4.17M
}
107
108
int asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t in_len,
109
2.80M
                  const ASN1_ITEM *it, CRYPTO_BUFFER *buf) {
110
2.80M
  ASN1_ENCODING *enc;
111
2.80M
  enc = asn1_get_enc_ptr(pval, it);
112
2.80M
  if (!enc) {
113
2.60M
    return 1;
114
2.60M
  }
115
116
198k
  asn1_encoding_clear(enc);
117
198k
  if (buf != NULL) {
118
193k
    assert(CRYPTO_BUFFER_data(buf) <= in &&
119
193k
           in + in_len <= CRYPTO_BUFFER_data(buf) + CRYPTO_BUFFER_len(buf));
120
193k
    CRYPTO_BUFFER_up_ref(buf);
121
193k
    enc->buf = buf;
122
193k
    enc->enc = (uint8_t *)in;
123
193k
  } else {
124
5.37k
    enc->enc = reinterpret_cast<uint8_t *>(OPENSSL_memdup(in, in_len));
125
5.37k
    if (!enc->enc) {
126
0
      return 0;
127
0
    }
128
5.37k
  }
129
130
198k
  enc->len = in_len;
131
198k
  return 1;
132
198k
}
133
134
436k
void asn1_encoding_clear(ASN1_ENCODING *enc) {
135
436k
  if (enc->buf != NULL) {
136
193k
    CRYPTO_BUFFER_free(enc->buf);
137
242k
  } else {
138
242k
    OPENSSL_free(enc->enc);
139
242k
  }
140
436k
  enc->enc = NULL;
141
436k
  enc->len = 0;
142
436k
  enc->buf = NULL;
143
436k
}
144
145
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
146
4.92M
                     const ASN1_ITEM *it) {
147
4.92M
  ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
148
4.92M
  if (!enc || enc->len == 0) {
149
4.87M
    return 0;
150
4.87M
  }
151
46.2k
  if (out) {
152
23.1k
    OPENSSL_memcpy(*out, enc->enc, enc->len);
153
23.1k
    *out += enc->len;
154
23.1k
  }
155
46.2k
  if (len) {
156
46.2k
    *len = enc->len;
157
46.2k
  }
158
46.2k
  return 1;
159
4.92M
}
160
161
// Given an ASN1_TEMPLATE get a pointer to a field
162
47.4M
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
163
47.4M
  ASN1_VALUE **pvaltmp =
164
47.4M
      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.4M
  return pvaltmp;
168
47.4M
}
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.6M
                                 int nullerr) {
174
32.6M
  const ASN1_ADB *adb;
175
32.6M
  const ASN1_ADB_TABLE *atbl;
176
32.6M
  ASN1_VALUE **sfld;
177
32.6M
  int i;
178
32.6M
  if (!(tt->flags & ASN1_TFLG_ADB_MASK)) {
179
32.6M
    return tt;
180
32.6M
  }
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.61k
    if (!adb->null_tt) {
192
1.61k
      goto err;
193
1.61k
    }
194
0
    return adb->null_tt;
195
1.61k
  }
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.84k
      return &atbl->tt;
211
6.84k
    }
212
20.8k
  }
213
214
  // FIXME: need to search application table too
215
216
  // No match, return default type
217
4.37k
  if (!adb->default_tt) {
218
0
    goto err;
219
0
  }
220
4.37k
  return adb->default_tt;
221
222
1.61k
err:
223
  // FIXME: should log the value or OID of unsupported type
224
1.61k
  if (nullerr) {
225
0
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
226
0
  }
227
1.61k
  return NULL;
228
4.37k
}