/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 | } |