/src/boringssl/crypto/asn1/tasn_utl.cc
Line | Count | Source |
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 | | using namespace bssl; |
31 | | |
32 | | // Utility functions for manipulating fields and offsets |
33 | | |
34 | | // Add 'offset' to 'addr' |
35 | 9.55M | #define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset)) |
36 | | |
37 | | // Given an ASN1_ITEM CHOICE type return the selector value |
38 | 525k | int bssl::asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
39 | 525k | int *sel = |
40 | 525k | reinterpret_cast<int *>(offset2ptr(asn1_load_ptr(pval), it->utype)); |
41 | 525k | return *sel; |
42 | 525k | } |
43 | | |
44 | | // Given an ASN1_ITEM CHOICE type set the selector value, return old value. |
45 | | int bssl::asn1_set_choice_selector(ASN1_VALUE **pval, int value, |
46 | 500k | const ASN1_ITEM *it) { |
47 | 500k | int *sel, ret; |
48 | 500k | sel = reinterpret_cast<int *>(offset2ptr(asn1_load_ptr(pval), it->utype)); |
49 | 500k | ret = *sel; |
50 | 500k | *sel = value; |
51 | 500k | return ret; |
52 | 500k | } |
53 | | |
54 | | static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval, |
55 | 1.57M | const ASN1_ITEM *it) { |
56 | 1.57M | if (it->itype != ASN1_ITYPE_SEQUENCE) { |
57 | 0 | return nullptr; |
58 | 0 | } |
59 | 1.57M | const ASN1_AUX *aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
60 | 1.57M | if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) { |
61 | 1.57M | return nullptr; |
62 | 1.57M | } |
63 | 0 | return reinterpret_cast<CRYPTO_refcount_t *>( |
64 | 0 | offset2ptr(asn1_load_ptr(pval), aux->ref_offset)); |
65 | 1.57M | } |
66 | | |
67 | 787k | void bssl::asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
68 | 787k | CRYPTO_refcount_t *references = asn1_get_references(pval, it); |
69 | 787k | if (references != nullptr) { |
70 | 0 | *references = 1; |
71 | 0 | } |
72 | 787k | } |
73 | | |
74 | | int bssl::asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, |
75 | 787k | const ASN1_ITEM *it) { |
76 | 787k | CRYPTO_refcount_t *references = asn1_get_references(pval, it); |
77 | 787k | if (references != nullptr) { |
78 | 0 | return CRYPTO_refcount_dec_and_test_zero(references); |
79 | 0 | } |
80 | 787k | return 1; |
81 | 787k | } |
82 | | |
83 | 2.38M | static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
84 | 2.38M | assert(it->itype == ASN1_ITYPE_SEQUENCE); |
85 | 2.38M | const ASN1_AUX *aux; |
86 | 2.38M | if (!pval || !asn1_load_ptr(pval)) { |
87 | 0 | return nullptr; |
88 | 0 | } |
89 | 2.38M | aux = reinterpret_cast<const ASN1_AUX *>(it->funcs); |
90 | 2.38M | if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) { |
91 | 2.38M | return nullptr; |
92 | 2.38M | } |
93 | 0 | return reinterpret_cast<ASN1_ENCODING *>( |
94 | 0 | offset2ptr(asn1_load_ptr(pval), aux->enc_offset)); |
95 | 2.38M | } |
96 | | |
97 | 787k | void bssl::asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
98 | 787k | ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); |
99 | 787k | if (enc) { |
100 | 0 | enc->enc = nullptr; |
101 | 0 | enc->len = 0; |
102 | 0 | } |
103 | 787k | } |
104 | | |
105 | 787k | void bssl::asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
106 | 787k | ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); |
107 | 787k | if (enc) { |
108 | 0 | asn1_encoding_clear(enc); |
109 | 0 | } |
110 | 787k | } |
111 | | |
112 | | int bssl::asn1_enc_save(ASN1_VALUE **pval, const uint8_t *in, size_t in_len, |
113 | 624k | const ASN1_ITEM *it) { |
114 | 624k | ASN1_ENCODING *enc; |
115 | 624k | enc = asn1_get_enc_ptr(pval, it); |
116 | 624k | if (!enc) { |
117 | 624k | return 1; |
118 | 624k | } |
119 | | |
120 | 0 | asn1_encoding_clear(enc); |
121 | 0 | enc->enc = reinterpret_cast<uint8_t *>(OPENSSL_memdup(in, in_len)); |
122 | 0 | if (!enc->enc) { |
123 | 0 | return 0; |
124 | 0 | } |
125 | | |
126 | 0 | enc->len = in_len; |
127 | 0 | return 1; |
128 | 0 | } |
129 | | |
130 | 0 | void bssl::asn1_encoding_clear(ASN1_ENCODING *enc) { |
131 | 0 | OPENSSL_free(enc->enc); |
132 | 0 | enc->enc = nullptr; |
133 | 0 | enc->len = 0; |
134 | 0 | } |
135 | | |
136 | | int bssl::asn1_enc_restore(Span<const uint8_t> *out, ASN1_VALUE **pval, |
137 | 184k | const ASN1_ITEM *it) { |
138 | 184k | ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it); |
139 | 184k | if (!enc || enc->len == 0) { |
140 | 184k | return 0; |
141 | 184k | } |
142 | 0 | *out = Span(enc->enc, enc->len); |
143 | 0 | return 1; |
144 | 184k | } |
145 | | |
146 | | // Given an ASN1_TEMPLATE get a pointer to a field |
147 | | ASN1_VALUE **bssl::asn1_get_field_ptr(ASN1_VALUE **pval, |
148 | 8.51M | const ASN1_TEMPLATE *tt) { |
149 | 8.51M | return reinterpret_cast<ASN1_VALUE **>( |
150 | 8.51M | offset2ptr(asn1_load_ptr(pval), tt->offset)); |
151 | 8.51M | } |
152 | | |
153 | | // Handle ANY DEFINED BY template, find the selector, look up the relevant |
154 | | // ASN1_TEMPLATE in the table and return it. |
155 | | const ASN1_TEMPLATE *bssl::asn1_do_adb(ASN1_VALUE **pval, |
156 | 4.64M | const ASN1_TEMPLATE *tt, int nullerr) { |
157 | 4.64M | if (!(tt->flags & ASN1_TFLG_ADB_MASK)) { |
158 | 4.63M | return tt; |
159 | 4.63M | } |
160 | | |
161 | | // Else ANY DEFINED BY ... get the table |
162 | 11.4k | const ASN1_ADB *adb = ASN1_ADB_ptr(tt->item); |
163 | | |
164 | | // Get the selector field |
165 | 11.4k | ASN1_VALUE **sfld = reinterpret_cast<ASN1_VALUE **>( |
166 | 11.4k | offset2ptr(asn1_load_ptr(pval), adb->offset)); |
167 | 11.4k | int selector; |
168 | 11.4k | const ASN1_OBJECT *selector_obj = asn1_load_ptr_as<ASN1_OBJECT>(sfld); |
169 | 11.4k | if (selector_obj == nullptr) { |
170 | 2.13k | if (!adb->null_tt) { |
171 | 2.13k | goto err; |
172 | 2.13k | } |
173 | 0 | return adb->null_tt; |
174 | 2.13k | } |
175 | | |
176 | | // Convert type to a NID: |
177 | | // NB: don't check for NID_undef here because it |
178 | | // might be a legitimate value in the table |
179 | 11.4k | assert(tt->flags & ASN1_TFLG_ADB_OID); |
180 | 9.30k | selector = OBJ_obj2nid(asn1_load_ptr_as<ASN1_OBJECT>(sfld)); |
181 | | |
182 | | // Try to find matching entry in table Maybe should check application types |
183 | | // first to allow application override? Might also be useful to have a flag |
184 | | // which indicates table is sorted and we can do a binary search. For now |
185 | | // stick to a linear search. |
186 | 20.8k | for (int i = 0; i < adb->tblcount; i++) { |
187 | 16.7k | const ASN1_ADB_TABLE *atbl = &adb->tbl[i]; |
188 | 16.7k | if (atbl->value == selector) { |
189 | 5.13k | return &atbl->tt; |
190 | 5.13k | } |
191 | 16.7k | } |
192 | | |
193 | | // No match, return default type |
194 | 4.16k | if (!adb->default_tt) { |
195 | 0 | goto err; |
196 | 0 | } |
197 | 4.16k | return adb->default_tt; |
198 | | |
199 | 2.13k | err: |
200 | | // FIXME: should log the value or OID of unsupported type |
201 | 2.13k | if (nullerr) { |
202 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); |
203 | 0 | } |
204 | 2.13k | return nullptr; |
205 | 4.16k | } |
206 | | |
207 | 1.42M | CBS_ASN1_TAG bssl::asn1_tag_to_cbs(int aclass, int tag) { |
208 | 1.42M | if ((aclass & ASN1_TFLG_TAG_CLASS) != aclass || // |
209 | 1.42M | tag < 0 || static_cast<CBS_ASN1_TAG>(tag) > CBS_ASN1_TAG_NUMBER_MASK || |
210 | | // Universal tag zero is reserved and should never appear in a template. |
211 | | // This file treats the zero tag as a sentinel value. |
212 | 1.42M | (aclass == 0 && tag == 0)) { |
213 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE); |
214 | 0 | return 0; |
215 | 0 | } |
216 | 1.42M | return ((static_cast<CBS_ASN1_TAG>(aclass)) << CBS_ASN1_TAG_SHIFT) | |
217 | 1.42M | static_cast<CBS_ASN1_TAG>(tag); |
218 | 1.42M | } |