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