/src/boringssl/crypto/x509/x_x509.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 <assert.h> |
16 | | #include <limits.h> |
17 | | #include <stdio.h> |
18 | | |
19 | | #include <openssl/asn1.h> |
20 | | #include <openssl/asn1t.h> |
21 | | #include <openssl/bytestring.h> |
22 | | #include <openssl/evp.h> |
23 | | #include <openssl/mem.h> |
24 | | #include <openssl/obj.h> |
25 | | #include <openssl/pool.h> |
26 | | #include <openssl/x509.h> |
27 | | |
28 | | #include "../asn1/internal.h" |
29 | | #include "../bytestring/internal.h" |
30 | | #include "../evp/internal.h" |
31 | | #include "../internal.h" |
32 | | #include "../mem_internal.h" |
33 | | #include "internal.h" |
34 | | |
35 | | |
36 | | using namespace bssl; |
37 | | |
38 | | static ExDataClass g_ex_data_class; |
39 | | |
40 | | static constexpr CBS_ASN1_TAG kVersionTag = |
41 | | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0; |
42 | | static constexpr CBS_ASN1_TAG kIssuerUIDTag = CBS_ASN1_CONTEXT_SPECIFIC | 1; |
43 | | static constexpr CBS_ASN1_TAG kSubjectUIDTag = CBS_ASN1_CONTEXT_SPECIFIC | 2; |
44 | | static constexpr CBS_ASN1_TAG kExtensionsTag = |
45 | | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3; |
46 | | |
47 | 205k | X509Impl::X509Impl() : RefCounted(CheckSubClass()) { |
48 | 205k | asn1_string_init(&serialNumber, V_ASN1_INTEGER); |
49 | 205k | x509_algor_init(&tbs_sig_alg); |
50 | 205k | x509_name_init(&issuer); |
51 | 205k | asn1_string_init(¬Before, -1); |
52 | 205k | asn1_string_init(¬After, -1); |
53 | 205k | x509_name_init(&subject); |
54 | 205k | x509_pubkey_init(&key); |
55 | 205k | x509_algor_init(&sig_alg); |
56 | 205k | asn1_string_init(&signature, V_ASN1_BIT_STRING); |
57 | 205k | CRYPTO_new_ex_data(&ex_data); |
58 | 205k | } |
59 | | |
60 | 205k | X509 *X509_new() { return New<X509Impl>(); } |
61 | | |
62 | 205k | X509Impl::~X509Impl() { |
63 | 205k | CRYPTO_free_ex_data(&g_ex_data_class, &ex_data); |
64 | | |
65 | 205k | asn1_string_cleanup(&serialNumber); |
66 | 205k | x509_algor_cleanup(&tbs_sig_alg); |
67 | 205k | x509_name_cleanup(&issuer); |
68 | 205k | asn1_string_cleanup(¬Before); |
69 | 205k | asn1_string_cleanup(¬After); |
70 | 205k | x509_name_cleanup(&subject); |
71 | 205k | x509_pubkey_cleanup(&key); |
72 | 205k | ASN1_BIT_STRING_free(issuerUID); |
73 | 205k | ASN1_BIT_STRING_free(subjectUID); |
74 | 205k | sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free); |
75 | 205k | x509_algor_cleanup(&sig_alg); |
76 | 205k | asn1_string_cleanup(&signature); |
77 | 205k | CRYPTO_BUFFER_free(buf); |
78 | 205k | ASN1_OCTET_STRING_free(skid); |
79 | 205k | AUTHORITY_KEYID_free(akid); |
80 | 205k | CRL_DIST_POINTS_free(crldp); |
81 | 205k | GENERAL_NAMES_free(altname); |
82 | 205k | NAME_CONSTRAINTS_free(nc); |
83 | 205k | X509_CERT_AUX_free(aux); |
84 | 205k | } |
85 | | |
86 | 873k | void X509_free(X509 *x509) { |
87 | 873k | if (x509 == nullptr) { |
88 | 477k | return; |
89 | 477k | } |
90 | 395k | auto *impl = FromOpaque(x509); |
91 | 395k | impl->DecRefInternal(); |
92 | 395k | } |
93 | | |
94 | | X509 *X509_parse_with_algorithms(CRYPTO_BUFFER *buf, |
95 | | const EVP_PKEY_ALG *const *algs, |
96 | 184k | size_t num_algs) { |
97 | 184k | UniquePtr<X509Impl> ret(FromOpaque(X509_new())); |
98 | 184k | if (ret == nullptr) { |
99 | 0 | return nullptr; |
100 | 0 | } |
101 | | |
102 | | // Save the buffer to cache the original encoding. |
103 | 184k | ret->buf = UpRef(buf).release(); |
104 | | |
105 | | // Parse the Certificate. |
106 | 184k | CBS cbs, cert, tbs; |
107 | 184k | CRYPTO_BUFFER_init_CBS(buf, &cbs); |
108 | 184k | if (!CBS_get_asn1(&cbs, &cert, CBS_ASN1_SEQUENCE) || // |
109 | 184k | CBS_len(&cbs) != 0 || |
110 | | // Bound the length to comfortably fit in an int. Lengths in this |
111 | | // module often omit overflow checks. |
112 | 184k | CBS_len(&cert) > INT_MAX / 2 || |
113 | 184k | !CBS_get_asn1(&cert, &tbs, CBS_ASN1_SEQUENCE) || |
114 | 183k | !x509_parse_algorithm(&cert, &ret->sig_alg) || |
115 | | // For just the signature field, we accept non-minimal BER lengths, though |
116 | | // not indefinite-length encoding. See b/18228011. |
117 | | // |
118 | | // TODO(crbug.com/boringssl/354): Switch the affected callers to convert |
119 | | // the certificate before parsing and then remove this workaround. |
120 | 179k | !asn1_parse_bit_string_with_bad_length(&cert, &ret->signature) || |
121 | 178k | CBS_len(&cert) != 0) { |
122 | 5.90k | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
123 | 5.90k | return nullptr; |
124 | 5.90k | } |
125 | | |
126 | | // Parse the TBSCertificate. |
127 | 178k | if (CBS_peek_asn1_tag(&tbs, kVersionTag)) { |
128 | 173k | CBS wrapper; |
129 | 173k | uint64_t version; |
130 | 173k | if (!CBS_get_asn1(&tbs, &wrapper, kVersionTag) || |
131 | 173k | !CBS_get_asn1_uint64(&wrapper, &version) || // |
132 | 173k | CBS_len(&wrapper) != 0) { |
133 | 297 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
134 | 297 | return nullptr; |
135 | 297 | } |
136 | | // The version must be one of v1(0), v2(1), or v3(2). |
137 | | // TODO(https://crbug.com/42290225): Also reject |X509_VERSION_1|. v1 is |
138 | | // DEFAULT, so DER requires it be omitted. |
139 | 173k | if (version != X509_VERSION_1 && version != X509_VERSION_2 && |
140 | 168k | version != X509_VERSION_3) { |
141 | 620 | OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION); |
142 | 620 | return nullptr; |
143 | 620 | } |
144 | 173k | ret->version = static_cast<uint8_t>(version); |
145 | 173k | } else { |
146 | 4.41k | ret->version = X509_VERSION_1; |
147 | 4.41k | } |
148 | 177k | CBS validity; |
149 | 177k | if (!asn1_parse_integer(&tbs, &ret->serialNumber, /*tag=*/0) || |
150 | 176k | !x509_parse_algorithm(&tbs, &ret->tbs_sig_alg) || |
151 | 176k | !x509_parse_name(&tbs, &ret->issuer) || |
152 | 176k | !CBS_get_asn1(&tbs, &validity, CBS_ASN1_SEQUENCE) || |
153 | 174k | !asn1_parse_time(&validity, &ret->notBefore, |
154 | 174k | /*allow_utc_timezone_offset=*/1) || |
155 | 174k | !asn1_parse_time(&validity, &ret->notAfter, |
156 | 174k | /*allow_utc_timezone_offset=*/1) || |
157 | 174k | CBS_len(&validity) != 0 || // |
158 | 174k | !x509_parse_name(&tbs, &ret->subject) || |
159 | 173k | !x509_parse_public_key(&tbs, &ret->key, Span(algs, num_algs))) { |
160 | 4.13k | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
161 | 4.13k | return nullptr; |
162 | 4.13k | } |
163 | | // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3: |
164 | 173k | if (ret->version >= X509_VERSION_2 && |
165 | 171k | CBS_peek_asn1_tag(&tbs, kIssuerUIDTag)) { |
166 | 5.13k | ret->issuerUID = ASN1_BIT_STRING_new(); |
167 | 5.13k | if (ret->issuerUID == nullptr || |
168 | 5.13k | !asn1_parse_bit_string(&tbs, ret->issuerUID, kIssuerUIDTag)) { |
169 | 44 | return nullptr; |
170 | 44 | } |
171 | 5.13k | } |
172 | 173k | if (ret->version >= X509_VERSION_2 && |
173 | 171k | CBS_peek_asn1_tag(&tbs, kSubjectUIDTag)) { |
174 | 326 | ret->subjectUID = ASN1_BIT_STRING_new(); |
175 | 326 | if (ret->subjectUID == nullptr || |
176 | 326 | !asn1_parse_bit_string(&tbs, ret->subjectUID, kSubjectUIDTag)) { |
177 | 61 | return nullptr; |
178 | 61 | } |
179 | 326 | } |
180 | | // Per RFC 5280, section 4.1.2.9, extensions require v3: |
181 | 173k | if (ret->version >= X509_VERSION_3 && |
182 | 166k | CBS_peek_asn1_tag(&tbs, kExtensionsTag)) { |
183 | 164k | CBS wrapper; |
184 | 164k | if (!CBS_get_asn1(&tbs, &wrapper, kExtensionsTag)) { |
185 | 41 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
186 | 41 | return nullptr; |
187 | 41 | } |
188 | | // TODO(crbug.com/442221114, crbug.com/42290219): Empty extension lists |
189 | | // should be rejected. Extensions is a SEQUENCE SIZE (1..MAX), so it cannot |
190 | | // be empty. An empty extensions list is encoded by omitting the OPTIONAL |
191 | | // field. libpki already rejects this. |
192 | 164k | const uint8_t *p = CBS_data(&wrapper); |
193 | 164k | ret->extensions = d2i_X509_EXTENSIONS(nullptr, &p, CBS_len(&wrapper)); |
194 | 164k | if (ret->extensions == nullptr || |
195 | 162k | p != CBS_data(&wrapper) + CBS_len(&wrapper)) { |
196 | 1.86k | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
197 | 1.86k | return nullptr; |
198 | 1.86k | } |
199 | 164k | } |
200 | 171k | if (CBS_len(&tbs) != 0) { |
201 | 1.06k | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
202 | 1.06k | return nullptr; |
203 | 1.06k | } |
204 | | |
205 | 170k | return ret.release(); |
206 | 171k | } |
207 | | |
208 | 184k | X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) { |
209 | 184k | auto algs = GetDefaultEVPAlgorithms(); |
210 | 184k | return X509_parse_with_algorithms(buf, algs.data(), algs.size()); |
211 | 184k | } |
212 | | |
213 | 12.2k | static UniquePtr<X509> x509_parse(CBS *cbs) { |
214 | 12.2k | CBS cert; |
215 | 12.2k | if (!CBS_get_asn1_element(cbs, &cert, CBS_ASN1_SEQUENCE)) { |
216 | 1.23k | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
217 | 1.23k | return nullptr; |
218 | 1.23k | } |
219 | | |
220 | 11.0k | UniquePtr<CRYPTO_BUFFER> buf(CRYPTO_BUFFER_new_from_CBS(&cert, nullptr)); |
221 | 11.0k | if (buf == nullptr) { |
222 | 0 | return nullptr; |
223 | 0 | } |
224 | 11.0k | return UniquePtr<X509>(X509_parse_from_buffer(buf.get())); |
225 | 11.0k | } |
226 | | |
227 | 43.2k | int bssl::x509_marshal_tbs_cert(CBB *cbb, const X509 *x509) { |
228 | 43.2k | auto *impl = FromOpaque(x509); |
229 | 43.2k | if (impl->buf != nullptr) { |
230 | | // Replay the saved TBSCertificate from the |CRYPTO_BUFFER|, to verify |
231 | | // exactly what we parsed. The |CRYPTO_BUFFER| contains the full |
232 | | // Certificate, so we need to find the TBSCertificate portion. |
233 | 40.0k | CBS cbs, cert, tbs; |
234 | 40.0k | CRYPTO_BUFFER_init_CBS(impl->buf, &cbs); |
235 | 40.0k | if (!CBS_get_asn1(&cbs, &cert, CBS_ASN1_SEQUENCE) || |
236 | 40.0k | !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE)) { |
237 | | // This should be impossible. |
238 | 0 | OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); |
239 | 0 | return 0; |
240 | 0 | } |
241 | 40.0k | return CBB_add_bytes(cbb, CBS_data(&tbs), CBS_len(&tbs)); |
242 | 40.0k | } |
243 | | |
244 | | // No saved TBSCertificate encoding. Encode it anew. |
245 | 3.19k | CBB tbs, version, validity, extensions; |
246 | 3.19k | if (!CBB_add_asn1(cbb, &tbs, CBS_ASN1_SEQUENCE)) { |
247 | 0 | return 0; |
248 | 0 | } |
249 | 3.19k | if (impl->version != X509_VERSION_1) { |
250 | 3.16k | if (!CBB_add_asn1(&tbs, &version, kVersionTag) || |
251 | 3.16k | !CBB_add_asn1_uint64(&version, impl->version)) { |
252 | 0 | return 0; |
253 | 0 | } |
254 | 3.16k | } |
255 | 3.19k | if (!asn1_marshal_integer(&tbs, &impl->serialNumber, /*tag=*/0) || |
256 | 3.19k | !x509_marshal_algorithm(&tbs, &impl->tbs_sig_alg) || |
257 | 3.19k | !x509_marshal_name(&tbs, &impl->issuer) || |
258 | 3.19k | !CBB_add_asn1(&tbs, &validity, CBS_ASN1_SEQUENCE) || |
259 | 3.19k | !asn1_marshal_time(&validity, &impl->notBefore) || |
260 | 3.19k | !asn1_marshal_time(&validity, &impl->notAfter) || |
261 | 3.19k | !x509_marshal_name(&tbs, &impl->subject) || |
262 | 3.19k | !x509_marshal_public_key(&tbs, &impl->key) || |
263 | 3.19k | (impl->issuerUID != nullptr && |
264 | 142 | !asn1_marshal_bit_string(&tbs, impl->issuerUID, kIssuerUIDTag)) || |
265 | 3.19k | (impl->subjectUID != nullptr && |
266 | 56 | !asn1_marshal_bit_string(&tbs, impl->subjectUID, kSubjectUIDTag))) { |
267 | 0 | return 0; |
268 | 0 | } |
269 | 3.19k | if (impl->extensions != nullptr) { |
270 | 2.84k | int len = i2d_X509_EXTENSIONS(impl->extensions, nullptr); |
271 | 2.84k | uint8_t *out; |
272 | 2.84k | if (len <= 0 || // |
273 | 2.84k | !CBB_add_asn1(&tbs, &extensions, kExtensionsTag) || |
274 | 2.84k | !CBB_add_space(&extensions, &out, len) || |
275 | 2.84k | i2d_X509_EXTENSIONS(impl->extensions, &out) != len) { |
276 | 0 | return 0; |
277 | 0 | } |
278 | 2.84k | } |
279 | 3.19k | return CBB_flush(cbb); |
280 | 3.19k | } |
281 | | |
282 | 40.0k | static int x509_marshal(CBB *cbb, const X509 *x509) { |
283 | 40.0k | CBB cert; |
284 | 40.0k | auto *impl = FromOpaque(x509); |
285 | 40.0k | return CBB_add_asn1(cbb, &cert, CBS_ASN1_SEQUENCE) && |
286 | 40.0k | x509_marshal_tbs_cert(&cert, x509) && |
287 | 40.0k | x509_marshal_algorithm(&cert, &impl->sig_alg) && |
288 | 40.0k | asn1_marshal_bit_string(&cert, &impl->signature, /*tag=*/0) && |
289 | 40.0k | CBB_flush(cbb); |
290 | 40.0k | } |
291 | | |
292 | 12.2k | X509 *d2i_X509(X509 **out, const uint8_t **inp, long len) { |
293 | 12.2k | return D2IFromCBS(out, inp, len, x509_parse); |
294 | 12.2k | } |
295 | | |
296 | 40.0k | int i2d_X509(const X509 *x509, uint8_t **outp) { |
297 | 40.0k | if (x509 == nullptr) { |
298 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE); |
299 | 0 | return -1; |
300 | 0 | } |
301 | | |
302 | 40.0k | return I2DFromCBB( |
303 | 40.0k | /*initial_capacity=*/256, outp, |
304 | 40.0k | [&](CBB *cbb) -> bool { return x509_marshal(cbb, x509); }); |
305 | 40.0k | } |
306 | | |
307 | 0 | static int x509_new_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
308 | 0 | *pval = (ASN1_VALUE *)X509_new(); |
309 | 0 | return *pval != nullptr; |
310 | 0 | } |
311 | | |
312 | 0 | static void x509_free_cb(ASN1_VALUE **pval, const ASN1_ITEM *it) { |
313 | 0 | X509_free((X509 *)*pval); |
314 | 0 | *pval = nullptr; |
315 | 0 | } |
316 | | |
317 | | static int x509_parse_cb(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
318 | 0 | int opt) { |
319 | 0 | if (opt && !CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) { |
320 | 0 | return 1; |
321 | 0 | } |
322 | | |
323 | 0 | UniquePtr<X509> ret = x509_parse(cbs); |
324 | 0 | if (ret == nullptr) { |
325 | 0 | return 0; |
326 | 0 | } |
327 | | |
328 | 0 | X509_free((X509 *)*pval); |
329 | 0 | *pval = (ASN1_VALUE *)ret.release(); |
330 | 0 | return 1; |
331 | 0 | } |
332 | | |
333 | | static int x509_i2d_cb(ASN1_VALUE **pval, unsigned char **out, |
334 | 0 | const ASN1_ITEM *it) { |
335 | 0 | return i2d_X509((X509 *)*pval, out); |
336 | 0 | } |
337 | | |
338 | | static const ASN1_EXTERN_FUNCS x509_extern_funcs = {x509_new_cb, x509_free_cb, |
339 | | x509_parse_cb, x509_i2d_cb}; |
340 | | IMPLEMENT_EXTERN_ASN1(X509, x509_extern_funcs) |
341 | | |
342 | 0 | X509 *X509_dup(const X509 *x509) { |
343 | 0 | uint8_t *der = nullptr; |
344 | 0 | int len = i2d_X509(x509, &der); |
345 | 0 | if (len < 0) { |
346 | 0 | return nullptr; |
347 | 0 | } |
348 | | |
349 | 0 | const uint8_t *inp = der; |
350 | 0 | X509 *ret = d2i_X509(nullptr, &inp, len); |
351 | 0 | OPENSSL_free(der); |
352 | 0 | return ret; |
353 | 0 | } |
354 | | |
355 | 203k | int X509_up_ref(X509 *x) { |
356 | 203k | auto *impl = FromOpaque(x); |
357 | 203k | impl->UpRefInternal(); |
358 | 203k | return 1; |
359 | 203k | } |
360 | | |
361 | | int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused, |
362 | | CRYPTO_EX_dup *dup_unused, |
363 | 0 | CRYPTO_EX_free *free_func) { |
364 | 0 | return CRYPTO_get_ex_new_index_ex(&g_ex_data_class, argl, argp, free_func); |
365 | 0 | } |
366 | | |
367 | 0 | int X509_set_ex_data(X509 *r, int idx, void *arg) { |
368 | 0 | auto *impl = FromOpaque(r); |
369 | 0 | return (CRYPTO_set_ex_data(&impl->ex_data, idx, arg)); |
370 | 0 | } |
371 | | |
372 | 0 | void *X509_get_ex_data(X509 *r, int idx) { |
373 | 0 | auto *impl = FromOpaque(r); |
374 | 0 | return (CRYPTO_get_ex_data(&impl->ex_data, idx)); |
375 | 0 | } |
376 | | |
377 | | // X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with |
378 | | // extra info tagged on the end. Since these functions set how a certificate |
379 | | // is trusted they should only be used when the certificate comes from a |
380 | | // reliable source such as local storage. |
381 | | |
382 | 0 | X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) { |
383 | 0 | const unsigned char *q = *pp; |
384 | 0 | X509 *ret; |
385 | 0 | int freeret = 0; |
386 | |
|
387 | 0 | if (!a || *a == nullptr) { |
388 | 0 | freeret = 1; |
389 | 0 | } |
390 | 0 | ret = d2i_X509(a, &q, length); |
391 | | // If certificate unreadable then forget it |
392 | 0 | if (!ret) { |
393 | 0 | return nullptr; |
394 | 0 | } |
395 | 0 | auto *impl = FromOpaque(ret); |
396 | | // update length |
397 | 0 | length -= q - *pp; |
398 | | // Parse auxiliary information if there is any. |
399 | 0 | if (length > 0 && !d2i_X509_CERT_AUX(&impl->aux, &q, length)) { |
400 | 0 | goto err; |
401 | 0 | } |
402 | 0 | *pp = q; |
403 | 0 | return ret; |
404 | 0 | err: |
405 | 0 | if (freeret) { |
406 | 0 | X509_free(ret); |
407 | 0 | if (a) { |
408 | 0 | *a = nullptr; |
409 | 0 | } |
410 | 0 | } |
411 | 0 | return nullptr; |
412 | 0 | } |
413 | | |
414 | | // Serialize trusted certificate to *pp or just return the required buffer |
415 | | // length if pp == NULL. We ultimately want to avoid modifying *pp in the |
416 | | // error path, but that depends on similar hygiene in lower-level functions. |
417 | | // Here we avoid compounding the problem. |
418 | 0 | static int i2d_x509_aux_internal(const X509 *a, unsigned char **pp) { |
419 | 0 | int length, tmplen; |
420 | 0 | unsigned char *start = pp != nullptr ? *pp : nullptr; |
421 | |
|
422 | 0 | assert(pp == nullptr || *pp != nullptr); |
423 | | |
424 | | // This might perturb *pp on error, but fixing that belongs in i2d_X509() |
425 | | // not here. It should be that if a == NULL length is zero, but we check |
426 | | // both just in case. |
427 | 0 | length = i2d_X509(a, pp); |
428 | 0 | if (length <= 0 || a == nullptr) { |
429 | 0 | return length; |
430 | 0 | } |
431 | | |
432 | 0 | auto *impl = FromOpaque(a); |
433 | 0 | if (impl->aux != nullptr) { |
434 | 0 | tmplen = i2d_X509_CERT_AUX(impl->aux, pp); |
435 | 0 | if (tmplen < 0) { |
436 | 0 | if (start != nullptr) { |
437 | 0 | *pp = start; |
438 | 0 | } |
439 | 0 | return tmplen; |
440 | 0 | } |
441 | 0 | length += tmplen; |
442 | 0 | } |
443 | | |
444 | 0 | return length; |
445 | 0 | } |
446 | | |
447 | | // Serialize trusted certificate to *pp, or just return the required buffer |
448 | | // length if pp == NULL. |
449 | | // |
450 | | // When pp is not NULL, but *pp == NULL, we allocate the buffer, but since |
451 | | // we're writing two ASN.1 objects back to back, we can't have i2d_X509() do |
452 | | // the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the |
453 | | // allocated buffer. |
454 | 0 | int i2d_X509_AUX(const X509 *a, unsigned char **pp) { |
455 | 0 | int length; |
456 | 0 | unsigned char *tmp; |
457 | | |
458 | | // Buffer provided by caller |
459 | 0 | if (pp == nullptr || *pp != nullptr) { |
460 | 0 | return i2d_x509_aux_internal(a, pp); |
461 | 0 | } |
462 | | |
463 | | // Obtain the combined length |
464 | 0 | if ((length = i2d_x509_aux_internal(a, nullptr)) <= 0) { |
465 | 0 | return length; |
466 | 0 | } |
467 | | |
468 | | // Allocate requisite combined storage |
469 | 0 | *pp = tmp = reinterpret_cast<uint8_t *>(OPENSSL_malloc(length)); |
470 | 0 | if (tmp == nullptr) { |
471 | 0 | return -1; // Push error onto error stack? |
472 | 0 | } |
473 | | |
474 | | // Encode, but keep *pp at the originally malloced pointer |
475 | 0 | length = i2d_x509_aux_internal(a, &tmp); |
476 | 0 | if (length <= 0) { |
477 | 0 | OPENSSL_free(*pp); |
478 | 0 | *pp = nullptr; |
479 | 0 | } |
480 | 0 | return length; |
481 | 0 | } |
482 | | |
483 | 3.19k | int i2d_re_X509_tbs(X509 *x509, uint8_t **outp) { |
484 | 3.19k | auto *impl = FromOpaque(x509); |
485 | 3.19k | CRYPTO_BUFFER_free(impl->buf); |
486 | 3.19k | impl->buf = nullptr; |
487 | 3.19k | return i2d_X509_tbs(x509, outp); |
488 | 3.19k | } |
489 | | |
490 | 3.19k | int i2d_X509_tbs(const X509 *x509, uint8_t **outp) { |
491 | 3.19k | return I2DFromCBB(/*initial_capacity=*/128, outp, [&](CBB *cbb) -> bool { |
492 | 3.19k | return x509_marshal_tbs_cert(cbb, x509); |
493 | 3.19k | }); |
494 | 3.19k | } |
495 | | |
496 | 0 | int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) { |
497 | 0 | auto *impl = FromOpaque(x509); |
498 | 0 | return X509_ALGOR_copy(&impl->sig_alg, algo) && |
499 | 0 | X509_ALGOR_copy(&impl->tbs_sig_alg, algo); |
500 | 0 | } |
501 | | |
502 | 0 | int X509_set1_signature_value(X509 *x509, const uint8_t *sig, size_t sig_len) { |
503 | 0 | return ASN1_STRING_set(&FromOpaque(x509)->signature, sig, sig_len); |
504 | 0 | } |
505 | | |
506 | | void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, |
507 | 0 | const X509 *x) { |
508 | 0 | const auto *impl = FromOpaque(x); |
509 | 0 | if (psig) { |
510 | 0 | *psig = &impl->signature; |
511 | 0 | } |
512 | 0 | if (palg) { |
513 | 0 | *palg = &impl->sig_alg; |
514 | 0 | } |
515 | 0 | } |
516 | | |
517 | 0 | int X509_get_signature_nid(const X509 *x) { |
518 | 0 | const auto *impl = FromOpaque(x); |
519 | 0 | return OBJ_obj2nid(impl->sig_alg.algorithm); |
520 | 0 | } |