• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57 /* ====================================================================
58  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
59  *
60  * Redistribution and use in source and binary forms, with or without
61  * modification, are permitted provided that the following conditions
62  * are met:
63  *
64  * 1. Redistributions of source code must retain the above copyright
65  *    notice, this list of conditions and the following disclaimer.
66  *
67  * 2. Redistributions in binary form must reproduce the above copyright
68  *    notice, this list of conditions and the following disclaimer in
69  *    the documentation and/or other materials provided with the
70  *    distribution.
71  *
72  * 3. All advertising materials mentioning features or use of this
73  *    software must display the following acknowledgment:
74  *    "This product includes software developed by the OpenSSL Project
75  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76  *
77  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78  *    endorse or promote products derived from this software without
79  *    prior written permission. For written permission, please contact
80  *    openssl-core@openssl.org.
81  *
82  * 5. Products derived from this software may not be called "OpenSSL"
83  *    nor may "OpenSSL" appear in their names without prior written
84  *    permission of the OpenSSL Project.
85  *
86  * 6. Redistributions of any form whatsoever must retain the following
87  *    acknowledgment:
88  *    "This product includes software developed by the OpenSSL Project
89  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90  *
91  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
95  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102  * OF THE POSSIBILITY OF SUCH DAMAGE.
103  * ====================================================================
104  *
105  * This product includes cryptographic software written by Eric Young
106  * (eay@cryptsoft.com).  This product includes software written by Tim
107  * Hudson (tjh@cryptsoft.com).
108  *
109  */
110 /* ====================================================================
111  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
112  * ECC cipher suite support in OpenSSL originally developed by
113  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */
114 
115 #include <openssl/ssl.h>
116 
117 #include <string.h>
118 
119 #include <openssl/bn.h>
120 #include <openssl/buf.h>
121 #include <openssl/ec_key.h>
122 #include <openssl/dh.h>
123 #include <openssl/err.h>
124 #include <openssl/mem.h>
125 #include <openssl/x509.h>
126 #include <openssl/x509v3.h>
127 
128 #include "../crypto/dh/internal.h"
129 #include "../crypto/internal.h"
130 #include "internal.h"
131 
132 
SSL_get_ex_data_X509_STORE_CTX_idx(void)133 int SSL_get_ex_data_X509_STORE_CTX_idx(void) {
134   /* The ex_data index to go from |X509_STORE_CTX| to |SSL| always uses the
135    * reserved app_data slot. Before ex_data was introduced, app_data was used.
136    * Avoid breaking any software which assumes |X509_STORE_CTX_get_app_data|
137    * works. */
138   return 0;
139 }
140 
ssl_cert_new(void)141 CERT *ssl_cert_new(void) {
142   CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
143   if (ret == NULL) {
144     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
145     return NULL;
146   }
147   memset(ret, 0, sizeof(CERT));
148 
149   return ret;
150 }
151 
ssl_cert_dup(CERT * cert)152 CERT *ssl_cert_dup(CERT *cert) {
153   CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
154   if (ret == NULL) {
155     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
156     return NULL;
157   }
158   memset(ret, 0, sizeof(CERT));
159 
160   ret->mask_k = cert->mask_k;
161   ret->mask_a = cert->mask_a;
162 
163   if (cert->dh_tmp != NULL) {
164     ret->dh_tmp = DHparams_dup(cert->dh_tmp);
165     if (ret->dh_tmp == NULL) {
166       OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
167       goto err;
168     }
169   }
170   ret->dh_tmp_cb = cert->dh_tmp_cb;
171 
172   if (cert->x509 != NULL) {
173     ret->x509 = X509_up_ref(cert->x509);
174   }
175 
176   if (cert->privatekey != NULL) {
177     ret->privatekey = EVP_PKEY_up_ref(cert->privatekey);
178   }
179 
180   if (cert->chain) {
181     ret->chain = X509_chain_up_ref(cert->chain);
182     if (!ret->chain) {
183       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
184       goto err;
185     }
186   }
187 
188   ret->cert_cb = cert->cert_cb;
189   ret->cert_cb_arg = cert->cert_cb_arg;
190 
191   return ret;
192 
193 err:
194   ssl_cert_free(ret);
195   return NULL;
196 }
197 
198 /* Free up and clear all certificates and chains */
ssl_cert_clear_certs(CERT * cert)199 void ssl_cert_clear_certs(CERT *cert) {
200   if (cert == NULL) {
201     return;
202   }
203 
204   X509_free(cert->x509);
205   cert->x509 = NULL;
206   EVP_PKEY_free(cert->privatekey);
207   cert->privatekey = NULL;
208   sk_X509_pop_free(cert->chain, X509_free);
209   cert->chain = NULL;
210   cert->key_method = NULL;
211 }
212 
ssl_cert_free(CERT * c)213 void ssl_cert_free(CERT *c) {
214   if (c == NULL) {
215     return;
216   }
217 
218   DH_free(c->dh_tmp);
219 
220   ssl_cert_clear_certs(c);
221   OPENSSL_free(c->peer_sigalgs);
222   OPENSSL_free(c->digest_nids);
223 
224   OPENSSL_free(c);
225 }
226 
ssl_cert_set0_chain(CERT * cert,STACK_OF (X509)* chain)227 int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
228   sk_X509_pop_free(cert->chain, X509_free);
229   cert->chain = chain;
230   return 1;
231 }
232 
ssl_cert_set1_chain(CERT * cert,STACK_OF (X509)* chain)233 int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
234   STACK_OF(X509) *dchain;
235   if (chain == NULL) {
236     return ssl_cert_set0_chain(cert, NULL);
237   }
238 
239   dchain = X509_chain_up_ref(chain);
240   if (dchain == NULL) {
241     return 0;
242   }
243 
244   if (!ssl_cert_set0_chain(cert, dchain)) {
245     sk_X509_pop_free(dchain, X509_free);
246     return 0;
247   }
248 
249   return 1;
250 }
251 
ssl_cert_add0_chain_cert(CERT * cert,X509 * x509)252 int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
253   if (cert->chain == NULL) {
254     cert->chain = sk_X509_new_null();
255   }
256   if (cert->chain == NULL || !sk_X509_push(cert->chain, x509)) {
257     return 0;
258   }
259 
260   return 1;
261 }
262 
ssl_cert_add1_chain_cert(CERT * cert,X509 * x509)263 int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
264   if (!ssl_cert_add0_chain_cert(cert, x509)) {
265     return 0;
266   }
267 
268   X509_up_ref(x509);
269   return 1;
270 }
271 
ssl_cert_set_cert_cb(CERT * c,int (* cb)(SSL * ssl,void * arg),void * arg)272 void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) {
273   c->cert_cb = cb;
274   c->cert_cb_arg = arg;
275 }
276 
ssl_verify_cert_chain(SSL * ssl,STACK_OF (X509)* cert_chain)277 int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain) {
278   if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
279     return 0;
280   }
281 
282   X509 *leaf = sk_X509_value(cert_chain, 0);
283   int ret = 0;
284   X509_STORE_CTX ctx;
285   if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, leaf, cert_chain)) {
286     OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
287     return 0;
288   }
289   if (!X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(),
290                                   ssl)) {
291     goto err;
292   }
293 
294   /* We need to inherit the verify parameters. These can be determined by the
295    * context: if its a server it will verify SSL client certificates or vice
296    * versa. */
297   X509_STORE_CTX_set_default(&ctx, ssl->server ? "ssl_client" : "ssl_server");
298 
299   /* Anything non-default in "param" should overwrite anything in the ctx. */
300   X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), ssl->param);
301 
302   if (ssl->verify_callback) {
303     X509_STORE_CTX_set_verify_cb(&ctx, ssl->verify_callback);
304   }
305 
306   if (ssl->ctx->app_verify_callback != NULL) {
307     ret = ssl->ctx->app_verify_callback(&ctx, ssl->ctx->app_verify_arg);
308   } else {
309     ret = X509_verify_cert(&ctx);
310   }
311 
312   ssl->verify_result = ctx.error;
313 
314 err:
315   X509_STORE_CTX_cleanup(&ctx);
316   return ret;
317 }
318 
set_client_CA_list(STACK_OF (X509_NAME)** ca_list,STACK_OF (X509_NAME)* name_list)319 static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,
320                                STACK_OF(X509_NAME) *name_list) {
321   sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
322   *ca_list = name_list;
323 }
324 
STACK_OF(X509_NAME)325 STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list) {
326   STACK_OF(X509_NAME) *ret = sk_X509_NAME_new_null();
327   if (ret == NULL) {
328     return NULL;
329   }
330 
331   size_t i;
332   for (i = 0; i < sk_X509_NAME_num(list); i++) {
333       X509_NAME *name = X509_NAME_dup(sk_X509_NAME_value(list, i));
334     if (name == NULL || !sk_X509_NAME_push(ret, name)) {
335       X509_NAME_free(name);
336       sk_X509_NAME_pop_free(ret, X509_NAME_free);
337       return NULL;
338     }
339   }
340 
341   return ret;
342 }
343 
SSL_set_client_CA_list(SSL * ssl,STACK_OF (X509_NAME)* name_list)344 void SSL_set_client_CA_list(SSL *ssl, STACK_OF(X509_NAME) *name_list) {
345   set_client_CA_list(&ssl->client_CA, name_list);
346 }
347 
SSL_CTX_set_client_CA_list(SSL_CTX * ctx,STACK_OF (X509_NAME)* name_list)348 void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) {
349   set_client_CA_list(&ctx->client_CA, name_list);
350 }
351 
STACK_OF(X509_NAME)352 STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) {
353   return ctx->client_CA;
354 }
355 
STACK_OF(X509_NAME)356 STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl) {
357   /* For historical reasons, this function is used both to query configuration
358    * state on a server as well as handshake state on a client. However, whether
359    * |ssl| is a client or server is not known until explicitly configured with
360    * |SSL_set_connect_state|. If |handshake_func| is NULL, |ssl| is in an
361    * indeterminate mode and |ssl->server| is unset. */
362   if (ssl->handshake_func != NULL && !ssl->server) {
363     return ssl->s3->tmp.ca_names;
364   }
365 
366   if (ssl->client_CA != NULL) {
367     return ssl->client_CA;
368   }
369   return ssl->ctx->client_CA;
370 }
371 
add_client_CA(STACK_OF (X509_NAME)** sk,X509 * x509)372 static int add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x509) {
373   X509_NAME *name;
374 
375   if (x509 == NULL) {
376     return 0;
377   }
378   if (*sk == NULL) {
379     *sk = sk_X509_NAME_new_null();
380     if (*sk == NULL) {
381       return 0;
382     }
383   }
384 
385   name = X509_NAME_dup(X509_get_subject_name(x509));
386   if (name == NULL) {
387     return 0;
388   }
389 
390   if (!sk_X509_NAME_push(*sk, name)) {
391     X509_NAME_free(name);
392     return 0;
393   }
394 
395   return 1;
396 }
397 
SSL_add_client_CA(SSL * ssl,X509 * x509)398 int SSL_add_client_CA(SSL *ssl, X509 *x509) {
399   return add_client_CA(&ssl->client_CA, x509);
400 }
401 
SSL_CTX_add_client_CA(SSL_CTX * ctx,X509 * x509)402 int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x509) {
403   return add_client_CA(&ctx->client_CA, x509);
404 }
405 
406 /* Add a certificate to a BUF_MEM structure */
ssl_add_cert_to_buf(BUF_MEM * buf,unsigned long * l,X509 * x)407 static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) {
408   int n;
409   uint8_t *p;
410 
411   n = i2d_X509(x, NULL);
412   if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
413     OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
414     return 0;
415   }
416   p = (uint8_t *)&(buf->data[*l]);
417   l2n3(n, p);
418   i2d_X509(x, &p);
419   *l += n + 3;
420 
421   return 1;
422 }
423 
424 /* Add certificate chain to internal SSL BUF_MEM structure. */
ssl_add_cert_chain(SSL * ssl,unsigned long * l)425 int ssl_add_cert_chain(SSL *ssl, unsigned long *l) {
426   CERT *cert = ssl->cert;
427   BUF_MEM *buf = ssl->init_buf;
428   int no_chain = 0;
429   size_t i;
430 
431   X509 *x = cert->x509;
432   STACK_OF(X509) *chain = cert->chain;
433 
434   if (x == NULL) {
435     OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
436     return 0;
437   }
438 
439   if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) || chain != NULL) {
440     no_chain = 1;
441   }
442 
443   if (no_chain) {
444     if (!ssl_add_cert_to_buf(buf, l, x)) {
445       return 0;
446     }
447 
448     for (i = 0; i < sk_X509_num(chain); i++) {
449       x = sk_X509_value(chain, i);
450       if (!ssl_add_cert_to_buf(buf, l, x)) {
451         return 0;
452       }
453     }
454   } else {
455     X509_STORE_CTX xs_ctx;
456 
457     if (!X509_STORE_CTX_init(&xs_ctx, ssl->ctx->cert_store, x, NULL)) {
458       OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
459       return 0;
460     }
461     X509_verify_cert(&xs_ctx);
462     /* Don't leave errors in the queue */
463     ERR_clear_error();
464     for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
465       x = sk_X509_value(xs_ctx.chain, i);
466 
467       if (!ssl_add_cert_to_buf(buf, l, x)) {
468         X509_STORE_CTX_cleanup(&xs_ctx);
469         return 0;
470       }
471     }
472     X509_STORE_CTX_cleanup(&xs_ctx);
473   }
474 
475   return 1;
476 }
477 
SSL_CTX_set0_chain(SSL_CTX * ctx,STACK_OF (X509)* chain)478 int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
479   return ssl_cert_set0_chain(ctx->cert, chain);
480 }
481 
SSL_CTX_set1_chain(SSL_CTX * ctx,STACK_OF (X509)* chain)482 int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
483   return ssl_cert_set1_chain(ctx->cert, chain);
484 }
485 
SSL_set0_chain(SSL * ssl,STACK_OF (X509)* chain)486 int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
487   return ssl_cert_set0_chain(ssl->cert, chain);
488 }
489 
SSL_set1_chain(SSL * ssl,STACK_OF (X509)* chain)490 int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
491   return ssl_cert_set1_chain(ssl->cert, chain);
492 }
493 
SSL_CTX_add0_chain_cert(SSL_CTX * ctx,X509 * x509)494 int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
495   return ssl_cert_add0_chain_cert(ctx->cert, x509);
496 }
497 
SSL_CTX_add1_chain_cert(SSL_CTX * ctx,X509 * x509)498 int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) {
499   return ssl_cert_add1_chain_cert(ctx->cert, x509);
500 }
501 
SSL_CTX_add_extra_chain_cert(SSL_CTX * ctx,X509 * x509)502 int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) {
503   return SSL_CTX_add0_chain_cert(ctx, x509);
504 }
505 
SSL_add0_chain_cert(SSL * ssl,X509 * x509)506 int SSL_add0_chain_cert(SSL *ssl, X509 *x509) {
507   return ssl_cert_add0_chain_cert(ssl->cert, x509);
508 }
509 
SSL_add1_chain_cert(SSL * ssl,X509 * x509)510 int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
511   return ssl_cert_add1_chain_cert(ssl->cert, x509);
512 }
513 
SSL_CTX_clear_chain_certs(SSL_CTX * ctx)514 int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
515   return SSL_CTX_set0_chain(ctx, NULL);
516 }
517 
SSL_CTX_clear_extra_chain_certs(SSL_CTX * ctx)518 int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) {
519   return SSL_CTX_clear_chain_certs(ctx);
520 }
521 
SSL_clear_chain_certs(SSL * ssl)522 int SSL_clear_chain_certs(SSL *ssl) {
523   return SSL_set0_chain(ssl, NULL);
524 }
525 
SSL_CTX_get0_chain_certs(const SSL_CTX * ctx,STACK_OF (X509)** out_chain)526 int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
527   *out_chain = ctx->cert->chain;
528   return 1;
529 }
530 
SSL_CTX_get_extra_chain_certs(const SSL_CTX * ctx,STACK_OF (X509)** out_chain)531 int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx,
532                                   STACK_OF(X509) **out_chain) {
533   return SSL_CTX_get0_chain_certs(ctx, out_chain);
534 }
535 
SSL_get0_chain_certs(const SSL * ssl,STACK_OF (X509)** out_chain)536 int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
537   *out_chain = ssl->cert->chain;
538   return 1;
539 }
540