- {
- CERT *c = s ? s->cert : ctx->cert;
- CERT_PKEY *cpk = c->key;
- X509_STORE *chain_store = NULL;
- X509_STORE_CTX xs_ctx;
- STACK_OF(X509) *chain = NULL, *untrusted = NULL;
- X509 *x;
- int i, rv = 0;
- unsigned long error;
-
- if (!cpk->x509)
- {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
- goto err;
- }
- /* Rearranging and check the chain: add everything to a store */
- if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
- {
- chain_store = X509_STORE_new();
- if (!chain_store)
- goto err;
- for (i = 0; i < sk_X509_num(cpk->chain); i++)
- {
- x = sk_X509_value(cpk->chain, i);
- if (!X509_STORE_add_cert(chain_store, x))
- {
- error = ERR_peek_last_error();
- if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
- ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
- goto err;
- ERR_clear_error();
- }
- }
- /* Add EE cert too: it might be self signed */
- if (!X509_STORE_add_cert(chain_store, cpk->x509))
- {
- error = ERR_peek_last_error();
- if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
- ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
- goto err;
- ERR_clear_error();
- }
- }
- else
- {
- if (c->chain_store)
- chain_store = c->chain_store;
- else if (s)
- chain_store = s->ctx->cert_store;
- else
- chain_store = ctx->cert_store;
-
- if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
- untrusted = cpk->chain;
- }
-
- if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted))
- {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
- goto err;
- }
- /* Set suite B flags if needed */
- X509_STORE_CTX_set_flags(&xs_ctx, c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
-
- i = X509_verify_cert(&xs_ctx);
- if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR)
- {
- if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
- ERR_clear_error();
- i = 1;
- rv = 2;
- }
- if (i > 0)
- chain = X509_STORE_CTX_get1_chain(&xs_ctx);
- if (i <= 0)
- {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
- i = X509_STORE_CTX_get_error(&xs_ctx);
- ERR_add_error_data(2, "Verify error:",
- X509_verify_cert_error_string(i));
-
- X509_STORE_CTX_cleanup(&xs_ctx);
- goto err;
- }
- X509_STORE_CTX_cleanup(&xs_ctx);
- /* Remove EE certificate from chain */
- x = sk_X509_shift(chain);
- X509_free(x);
- if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT)
- {
- if (sk_X509_num(chain) > 0)
- {
- /* See if last cert is self signed */
- x = sk_X509_value(chain, sk_X509_num(chain) - 1);
- X509_check_purpose(x, -1, 0);
- if (x->ex_flags & EXFLAG_SS)
- {
- x = sk_X509_pop(chain);
- X509_free(x);
- }
- }
- }
- /* Check security level of all CA certificates: EE will have been
- * checked already.
- */
- for (i = 0; i < sk_X509_num(chain); i++)
- {
- x = sk_X509_value(chain, i);
- rv = ssl_security_cert(s, ctx, x, 0, 0);
- if (rv != 1)
- {
- SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, rv);
- sk_X509_pop_free(chain, X509_free);
- rv = 0;
- goto err;
- }
- }
- if (cpk->chain)
- sk_X509_pop_free(cpk->chain, X509_free);
- cpk->chain = chain;
- if (rv == 0)
- rv = 1;
- err:
- if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
- X509_STORE_free(chain_store);
-
- return rv;
- }
+{
+ CERT *c = s ? s->cert : ctx->cert;
+ CERT_PKEY *cpk = c->key;
+ X509_STORE *chain_store = NULL;
+ X509_STORE_CTX xs_ctx;
+ STACK_OF(X509) *chain = NULL, *untrusted = NULL;
+ X509 *x;
+ int i, rv = 0;
+ unsigned long error;
+
+ if (!cpk->x509) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
+ goto err;
+ }
+ /* Rearranging and check the chain: add everything to a store */
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
+ chain_store = X509_STORE_new();
+ if (!chain_store)
+ goto err;
+ for (i = 0; i < sk_X509_num(cpk->chain); i++) {
+ x = sk_X509_value(cpk->chain, i);
+ if (!X509_STORE_add_cert(chain_store, x)) {
+ error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error) !=
+ X509_R_CERT_ALREADY_IN_HASH_TABLE)
+ goto err;
+ ERR_clear_error();
+ }
+ }
+ /* Add EE cert too: it might be self signed */
+ if (!X509_STORE_add_cert(chain_store, cpk->x509)) {
+ error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
+ ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
+ goto err;
+ ERR_clear_error();
+ }
+ } else {
+ if (c->chain_store)
+ chain_store = c->chain_store;
+ else if (s)
+ chain_store = s->ctx->cert_store;
+ else
+ chain_store = ctx->cert_store;
+
+ if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
+ untrusted = cpk->chain;
+ }
+
+ if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
+ goto err;
+ }
+ /* Set suite B flags if needed */
+ X509_STORE_CTX_set_flags(&xs_ctx,
+ c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
+
+ i = X509_verify_cert(&xs_ctx);
+ if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
+ if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
+ ERR_clear_error();
+ i = 1;
+ rv = 2;
+ }
+ if (i > 0)
+ chain = X509_STORE_CTX_get1_chain(&xs_ctx);
+ if (i <= 0) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ i = X509_STORE_CTX_get_error(&xs_ctx);
+ ERR_add_error_data(2, "Verify error:",
+ X509_verify_cert_error_string(i));
+
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ goto err;
+ }
+ X509_STORE_CTX_cleanup(&xs_ctx);
+ /* Remove EE certificate from chain */
+ x = sk_X509_shift(chain);
+ X509_free(x);
+ if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
+ if (sk_X509_num(chain) > 0) {
+ /* See if last cert is self signed */
+ x = sk_X509_value(chain, sk_X509_num(chain) - 1);
+ X509_check_purpose(x, -1, 0);
+ if (x->ex_flags & EXFLAG_SS) {
+ x = sk_X509_pop(chain);
+ X509_free(x);
+ }
+ }
+ }
+ /*
+ * Check security level of all CA certificates: EE will have been checked
+ * already.
+ */
+ for (i = 0; i < sk_X509_num(chain); i++) {
+ x = sk_X509_value(chain, i);
+ rv = ssl_security_cert(s, ctx, x, 0, 0);
+ if (rv != 1) {
+ SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, rv);
+ sk_X509_pop_free(chain, X509_free);
+ rv = 0;
+ goto err;
+ }
+ }
+ sk_X509_pop_free(cpk->chain, X509_free);
+ cpk->chain = chain;
+ if (rv == 0)
+ rv = 1;
+ err:
+ if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
+ X509_STORE_free(chain_store);
+
+ return rv;
+}