bool Chain::checkIssued(Handle<Certificate> issuer, Handle<Certificate> cert){ LOGGER_FN(); try{ int ret; X509 *iss = NULL; iss = issuer->internal(); if (!iss){ THROW_EXCEPTION(0, Chain, NULL, "iss"); } X509 *sub = NULL; sub = cert->internal(); if (!sub){ THROW_EXCEPTION(0, Chain, NULL, "sub"); } LOGGER_OPENSSL(X509_check_issued); ret = X509_check_issued(iss, sub); if (ret == X509_V_OK){ return 1; } else{ return 0; } } catch (Handle<Exception> e){ THROW_EXCEPTION(0, Chain, e, "checkIssued"); } }
int lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted, const char *common_name) { char c[32], *p; int ret; if (common_name) { X509_NAME *xn = X509_get_subject_name(x509->cert); if (!xn) return -1; X509_NAME_oneline(xn, c, (int)sizeof(c) - 2); p = strstr(c, "/CN="); if (p) p = p + 4; else p = c; if (strcmp(p, common_name)) { lwsl_err("%s: common name mismatch\n", __func__); return -1; } } ret = X509_check_issued(trusted->cert, x509->cert); if (ret != X509_V_OK) { lwsl_err("%s: unable to verify cert relationship\n", __func__); lws_tls_err_describe(); return -1; } return 0; }
int SslOcspStapling::getCertId(X509 *pCert) { int i, n; X509 *pXissuer; X509_STORE *pXstore; STACK_OF(X509) *pXchain; X509_STORE_CTX *pXstore_ctx; pXchain = m_pCtx->extra_certs; n = sk_X509_num(pXchain); for (i = 0; i < n; i++) { pXissuer = sk_X509_value(pXchain, i); if (X509_check_issued(pXissuer, pCert) == X509_V_OK) { CRYPTO_add(&pXissuer->references, 1, CRYPTO_LOCK_X509); m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer); X509_free(pXissuer); return 0; } } pXstore = SSL_CTX_get_cert_store(m_pCtx); if (pXstore == NULL) { setLastErrMsg("SSL_CTX_get_cert_store failed!\n"); return LS_FAIL; } pXstore_ctx = X509_STORE_CTX_new(); if (pXstore_ctx == NULL) { setLastErrMsg("X509_STORE_CTX_new failed!\n"); return LS_FAIL; } if (X509_STORE_CTX_init(pXstore_ctx, pXstore, NULL, NULL) == 0) { setLastErrMsg("X509_STORE_CTX_init failed!\n"); return LS_FAIL; } n = X509_STORE_CTX_get1_issuer(&pXissuer, pXstore_ctx, pCert); X509_STORE_CTX_free(pXstore_ctx); if ((n == -1) || (n == 0)) { setLastErrMsg("X509_STORE_CTX_get1_issuer failed!\n"); return LS_FAIL; } m_pCertId = OCSP_cert_to_id(NULL, pCert, pXissuer); X509_free(pXissuer); return 0; }
int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc, server_rec *s, conn_rec *c, apr_pool_t *pool) { X509 *cert = X509_STORE_CTX_get_current_cert(ctx); apr_pool_t *vpool; int rv; if (!cert) { /* starting with OpenSSL 1.0, X509_STORE_CTX_get_current_cert() * may yield NULL. Return early, but leave the ctx error as is. */ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "No cert available to check with OCSP"); return 1; } else if (cert->valid && X509_check_issued(cert,cert) == X509_V_OK) { /* don't do OCSP checking for valid self-issued certs */ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, "Skipping OCSP check for valid self-issued cert"); X509_STORE_CTX_set_error(ctx, X509_V_OK); return 1; } /* Create a temporary pool to constrain memory use (the passed-in * pool may be e.g. a connection pool). */ apr_pool_create(&vpool, pool); rv = verify_ocsp_status(cert, ctx, c, sc, s, vpool); apr_pool_destroy(vpool); /* Propagate the verification status back to the passed-in * context. */ switch (rv) { case V_OCSP_CERTSTATUS_GOOD: X509_STORE_CTX_set_error(ctx, X509_V_OK); break; case V_OCSP_CERTSTATUS_REVOKED: X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); break; case V_OCSP_CERTSTATUS_UNKNOWN: /* correct error code for application errors? */ X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION); break; } return rv == V_OCSP_CERTSTATUS_GOOD; }
static void workaround_openssl_certchain_bug(struct openconnect_info *vpninfo, SSL *ssl) { /* OpenSSL has problems with certificate chains -- if there are multiple certs with the same name, it doesn't necessarily choose the _right_ one. (RT#1942) Pick the right ones for ourselves and add them manually. */ X509 *cert = SSL_get_certificate(ssl); X509 *cert2; X509_STORE *store = SSL_CTX_get_cert_store(vpninfo->https_ctx); X509_STORE_CTX ctx; if (!cert || !store) return; /* If we already have 'supporting' certs, don't add them again */ if (vpninfo->https_ctx->extra_certs) return; if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) return; while (ctx.get_issuer(&cert2, &ctx, cert) == 1) { char buf[200]; if (cert2 == cert) break; if (X509_check_issued(cert2, cert2) == X509_V_OK) break; cert = cert2; X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_DEBUG, _("Extra cert from cafile: '%s'\n"), buf); SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert); } X509_STORE_CTX_cleanup(&ctx); }
static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12) { EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *ca; int ret = 0; char *pass; pass = vpninfo->cert_password; vpninfo->cert_password = NULL; retrypass: /* We do this every time round the loop, to work around a bug in OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed when PKCS12_parse() returns an error, but *ca is left pointing to the freed memory. */ ca = NULL; if (!pass && request_passphrase(vpninfo, "openconnect_pkcs12", &pass, _("Enter PKCS#12 pass phrase:")) < 0) { PKCS12_free(p12); return -EINVAL; } if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { unsigned long err = ERR_peek_error(); openconnect_report_ssl_errors(vpninfo); if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 && ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE && ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) { vpn_progress(vpninfo, PRG_ERR, _("Parse PKCS#12 failed (wrong passphrase?)\n")); free(pass); pass = NULL; goto retrypass; } vpn_progress(vpninfo, PRG_ERR, _("Parse PKCS#12 failed (see above errors)\n")); PKCS12_free(p12); free(pass); return -EINVAL; } free(pass); if (cert) { char buf[200]; vpninfo->cert_x509 = cert; SSL_CTX_use_certificate(vpninfo->https_ctx, cert); X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"), buf); } else { vpn_progress(vpninfo, PRG_ERR, _("PKCS#12 contained no certificate!")); ret = -EINVAL; } if (pkey) { SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey); EVP_PKEY_free(pkey); } else { vpn_progress(vpninfo, PRG_ERR, _("PKCS#12 contained no private key!")); ret = -EINVAL; } /* Only include supporting certificates which are actually necessary */ if (ca) { int i; next: for (i = 0; i < sk_X509_num(ca); i++) { X509 *cert2 = sk_X509_value(ca, i); if (X509_check_issued(cert2, cert) == X509_V_OK) { char buf[200]; if (cert2 == cert) break; if (X509_check_issued(cert2, cert2) == X509_V_OK) break; X509_NAME_oneline(X509_get_subject_name(cert2), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_DEBUG, _("Extra cert from PKCS#12: '%s'\n"), buf); CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509); SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2); cert = cert2; goto next; } } sk_X509_pop_free(ca, X509_free); } PKCS12_free(p12); return ret; }
static int do_ca_cert_bootstrap(struct stream *stream) { struct ssl_stream *sslv = ssl_stream_cast(stream); STACK_OF(X509) *chain; X509 *cert; FILE *file; int error; int fd; chain = SSL_get_peer_cert_chain(sslv->ssl); if (!chain || !sk_X509_num(chain)) { VLOG_ERR("could not bootstrap CA cert: no certificate presented by " "peer"); return EPROTO; } cert = sk_X509_value(chain, sk_X509_num(chain) - 1); /* Check that 'cert' is self-signed. Otherwise it is not a CA * certificate and we should not attempt to use it as one. */ error = X509_check_issued(cert, cert); if (error) { VLOG_ERR("could not bootstrap CA cert: obtained certificate is " "not self-signed (%s)", X509_verify_cert_error_string(error)); if (sk_X509_num(chain) < 2) { VLOG_ERR("only one certificate was received, so probably the peer " "is not configured to send its CA certificate"); } return EPROTO; } fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444); if (fd < 0) { if (errno == EEXIST) { VLOG_INFO_RL(&rl, "reading CA cert %s created by another process", ca_cert.file_name); stream_ssl_set_ca_cert_file__(ca_cert.file_name, true, true); return EPROTO; } else { VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", ca_cert.file_name, ovs_strerror(errno)); return errno; } } file = fdopen(fd, "w"); if (!file) { error = errno; VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s", ovs_strerror(error)); unlink(ca_cert.file_name); return error; } if (!PEM_write_X509(file, cert)) { VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: " "%s", ca_cert.file_name, ERR_error_string(ERR_get_error(), NULL)); fclose(file); unlink(ca_cert.file_name); return EIO; } if (fclose(file)) { error = errno; VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s", ca_cert.file_name, ovs_strerror(error)); unlink(ca_cert.file_name); return error; } VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert.file_name); log_ca_cert(ca_cert.file_name, cert); bootstrap_ca_cert = false; ca_cert.read = true; /* SSL_CTX_add_client_CA makes a copy of cert's relevant data. */ SSL_CTX_add_client_CA(ctx, cert); SSL_CTX_set_cert_store(ctx, X509_STORE_new()); if (SSL_CTX_load_verify_locations(ctx, ca_cert.file_name, NULL) != 1) { VLOG_ERR("SSL_CTX_load_verify_locations: %s", ERR_error_string(ERR_get_error(), NULL)); return EPROTO; } VLOG_INFO("killing successful connection to retry using CA cert"); return EPROTO; }
static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) { int i, n, rc; X509 *cert, *issuer; X509_STORE *store; X509_STORE_CTX *store_ctx; STACK_OF(X509) *chain; ngx_ssl_stapling_t *staple; staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); #if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); #else chain = ssl->ctx->extra_certs; #endif n = sk_X509_num(chain); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: %d extra certs", n); for (i = 0; i < n; i++) { issuer = sk_X509_value(chain, i); if (X509_check_issued(issuer, cert) == X509_V_OK) { #if OPENSSL_VERSION_NUMBER >= 0x10100001L X509_up_ref(issuer); #else CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509); #endif ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in extra certs", issuer); staple->cert = cert; staple->issuer = issuer; return NGX_OK; } } store = SSL_CTX_get_cert_store(ssl->ctx); if (store == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_get_cert_store() failed"); return NGX_ERROR; } store_ctx = X509_STORE_CTX_new(); if (store_ctx == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_new() failed"); return NGX_ERROR; } if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_init() failed"); X509_STORE_CTX_free(store_ctx); return NGX_ERROR; } rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert); if (rc == -1) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_get1_issuer() failed"); X509_STORE_CTX_free(store_ctx); return NGX_ERROR; } if (rc == 0) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, issuer certificate not found"); X509_STORE_CTX_free(store_ctx); return NGX_DECLINED; } X509_STORE_CTX_free(store_ctx); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in cert store", issuer); staple->cert = cert; staple->issuer = issuer; return NGX_OK; }
/** * NOTE: From node.js * * Read a file that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. * * Taken from OpenSSL - editted for style. */ int bud_context_use_certificate_chain(bud_context_t* ctx, BIO *in) { int ret; X509* x; X509* ca; X509_STORE* store; X509_STORE_CTX store_ctx; int r; unsigned long err; ERR_clear_error(); ret = 0; x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } ret = SSL_CTX_use_certificate(ctx->ctx, x); ctx->cert = x; ctx->issuer = NULL; if (ERR_peek_error() != 0) { /* Key/certificate mismatch doesn't imply ret==0 ... */ ret = 0; } if (ret) { /** * If we could set up our certificate, now proceed to * the CA certificates. */ if (ctx->ctx->extra_certs != NULL) { sk_X509_pop_free(ctx->ctx->extra_certs, X509_free); ctx->ctx->extra_certs = NULL; } while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) { r = SSL_CTX_add_extra_chain_cert(ctx->ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /** * Note that we must not free r if it was successfully * added to the chain (while we must free the main * certificate, since its reference count is increased * by SSL_CTX_use_certificate). */ /* Find issuer */ if (ctx->issuer != NULL || X509_check_issued(ca, x) != X509_V_OK) continue; ctx->issuer = ca; } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { /* some real error */ ret = 0; } } end: if (ret) { /* Try getting issuer from cert store */ if (ctx->issuer == NULL) { store = SSL_CTX_get_cert_store(ctx->ctx); ret = X509_STORE_CTX_init(&store_ctx, store, NULL, NULL); if (!ret) goto fatal; ret = X509_STORE_CTX_get1_issuer(&ctx->issuer, &store_ctx, ctx->cert); X509_STORE_CTX_cleanup(&store_ctx); ret = ret < 0 ? 0 : 1; /* NOTE: get_cert_store doesn't increment reference count */ } else { /* Increment issuer reference count */ CRYPTO_add(&ctx->issuer->references, 1, CRYPTO_LOCK_X509); } if (ctx->issuer != NULL) { /* Get ocsp_id */ ctx->ocsp_id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer); if (ctx->ocsp_id == NULL) { ctx->issuer = NULL; goto fatal; } } } else { if (ctx->issuer != NULL) X509_free(ctx->issuer); } fatal: if (ctx->cert != x && x != NULL) X509_free(x); return ret; }
bool CertificateIsSelfSigned(X509* cert) { bool self_signed = (X509_check_issued(cert, cert) == X509_V_OK); return self_signed; }
extern "C" int32_t CryptoNative_X509CheckIssued(X509* issuer, X509* subject) { return X509_check_issued(issuer, subject); }
/** * NOTE: From node.js * * Read a file that contains our certificate in "PEM" format, * possibly followed by a sequence of CA certificates that should be * sent to the peer in the Certificate message. * * Taken from OpenSSL - editted for style. */ int bud_context_use_certificate_chain(bud_context_t* ctx, BIO *in) { int ret; X509* x; X509* ca; int r; unsigned long err; bud_context_pkey_type_t type; bud_context_pem_t* pem; ERR_clear_error(); ret = 0; x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL); pem = NULL; if (x == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); goto end; } ret = SSL_CTX_use_certificate(ctx->ctx, x); SSL_CTX_select_current_cert(ctx->ctx, x); type = bud_config_pkey_type(x->cert_info->key->pkey); pem = &ctx->pem[type]; pem->cert = x; pem->issuer = NULL; if (ERR_peek_error() != 0) { /* Key/certificate mismatch doesn't imply ret==0 ... */ ret = 0; } if (ret) { while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) { /* * Extra cert - add it to store to make OpenSSL pick and send proper * certs automatically */ r = SSL_CTX_add1_chain_cert(ctx->ctx, ca); if (!r) { X509_free(ca); ret = 0; goto end; } /** * Note that we must not free r if it was successfully * added to the chain (while we must free the main * certificate, since its reference count is increased * by SSL_CTX_use_certificate). */ /* Find issuer */ if (pem->issuer != NULL || X509_check_issued(ca, x) != X509_V_OK) continue; pem->issuer = ca; } /* When the while loop ends, it's usually just EOF. */ err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { ERR_clear_error(); } else { /* some real error */ ret = 0; } } end: if (ret) { /* Try getting issuer from cert store */ if (pem->issuer == NULL) { X509_STORE* store; X509_STORE_CTX store_ctx; store = SSL_CTX_get_cert_store(ctx->ctx); ret = X509_STORE_CTX_init(&store_ctx, store, NULL, NULL); if (!ret) goto fatal; ret = X509_STORE_CTX_get1_issuer(&pem->issuer, &store_ctx, pem->cert); X509_STORE_CTX_cleanup(&store_ctx); ret = ret < 0 ? 0 : 1; /* NOTE: get_cert_store doesn't increment reference count */ } else { /* Increment issuer reference count */ CRYPTO_add(&pem->issuer->references, 1, CRYPTO_LOCK_X509); } if (pem->issuer != NULL) { /* Get ocsp_id */ pem->ocsp_id = OCSP_cert_to_id(NULL, pem->cert, pem->issuer); if (pem->ocsp_id == NULL) goto fatal; } } fatal: if (!ret && pem != NULL && pem->issuer != NULL) { X509_free(pem->issuer); pem->issuer = NULL; } if (!(pem != NULL && pem->cert == x) && x != NULL) X509_free(x); return ret; }
static int do_ca_cert_bootstrap(struct vconn *vconn) { struct ssl_vconn *sslv = ssl_vconn_cast(vconn); STACK_OF(X509) *chain; X509 *ca_cert; FILE *file; int error; int fd; chain = SSL_get_peer_cert_chain(sslv->ssl); if (!chain || !sk_X509_num(chain)) { VLOG_ERR("could not bootstrap CA cert: no certificate presented by " "peer"); return EPROTO; } ca_cert = sk_X509_value(chain, sk_X509_num(chain) - 1); /* Check that 'ca_cert' is self-signed. Otherwise it is not a CA * certificate and we should not attempt to use it as one. */ error = X509_check_issued(ca_cert, ca_cert); if (error) { VLOG_ERR("could not bootstrap CA cert: obtained certificate is " "not self-signed (%s)", X509_verify_cert_error_string(error)); if (sk_X509_num(chain) < 2) { VLOG_ERR("only one certificate was received, so probably the peer " "is not configured to send its CA certificate"); } return EPROTO; } fd = open(ca_cert_file, O_CREAT | O_EXCL | O_WRONLY, 0444); if (fd < 0) { VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", ca_cert_file, strerror(errno)); return errno; } file = fdopen(fd, "w"); if (!file) { int error = errno; VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s", strerror(error)); unlink(ca_cert_file); return error; } if (!PEM_write_X509(file, ca_cert)) { VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: " "%s", ca_cert_file, ERR_error_string(ERR_get_error(), NULL)); fclose(file); unlink(ca_cert_file); return EIO; } if (fclose(file)) { int error = errno; VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s", ca_cert_file, strerror(error)); unlink(ca_cert_file); return error; } VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert_file); log_ca_cert(ca_cert_file, ca_cert); bootstrap_ca_cert = false; has_ca_cert = true; /* SSL_CTX_add_client_CA makes a copy of ca_cert's relevant data. */ SSL_CTX_add_client_CA(ctx, ca_cert); /* SSL_CTX_use_certificate() takes ownership of the certificate passed in. * 'ca_cert' is owned by sslv->ssl, so we need to duplicate it. */ ca_cert = X509_dup(ca_cert); if (!ca_cert) { out_of_memory(); } if (SSL_CTX_load_verify_locations(ctx, ca_cert_file, NULL) != 1) { VLOG_ERR("SSL_CTX_load_verify_locations: %s", ERR_error_string(ERR_get_error(), NULL)); return EPROTO; } VLOG_INFO("killing successful connection to retry using CA cert"); return EPROTO; }
s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator, struct s2n_connection *conn, const uint8_t *ocsp_response_raw, uint32_t ocsp_response_length) { if (validator->skip_cert_validation || !validator->check_stapled_ocsp) { return S2N_CERT_OK; } #if !S2N_OCSP_STAPLING_SUPPORTED /* Default to safety */ return S2N_CERT_ERR_UNTRUSTED; #else OCSP_RESPONSE *ocsp_response = NULL; OCSP_BASICRESP *basic_response = NULL; s2n_cert_validation_code ret_val = S2N_CERT_ERR_INVALID; if (!ocsp_response_raw) { return ret_val; } ocsp_response = d2i_OCSP_RESPONSE(NULL, &ocsp_response_raw, ocsp_response_length); if (!ocsp_response) { goto clean_up; } int ocsp_status = OCSP_response_status(ocsp_response); if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { goto clean_up; } basic_response = OCSP_response_get1_basic(ocsp_response); if (!basic_response) { goto clean_up; } int i; int certs_in_chain = sk_X509_num(validator->cert_chain); int certs_in_ocsp = sk_X509_num(OCSP_GET_CERTS(basic_response)); if (certs_in_chain >= 2 && certs_in_ocsp >= 1) { X509 *responder = sk_X509_value(OCSP_GET_CERTS(basic_response), certs_in_ocsp - 1); /*check to see if one of the certs in the chain is an issuer of the cert in the ocsp response.*/ /*if so it needs to be added to the OCSP verification chain.*/ for (i = 0; i < certs_in_chain; i++) { X509 *issuer = sk_X509_value(validator->cert_chain, i); int issuer_value = X509_check_issued(issuer, responder); if (issuer_value == X509_V_OK) { if (!OCSP_basic_add1_cert(basic_response, issuer)) { goto clean_up; } } } } int ocsp_verify_err = OCSP_basic_verify(basic_response, validator->cert_chain, validator->trust_store->trust_store, 0); /* do the crypto checks on the response.*/ if (!ocsp_verify_err) { ret_val = S2N_CERT_ERR_EXPIRED; goto clean_up; } /* for each response check the timestamps and the status. */ for (i = 0; i < OCSP_resp_count(basic_response); i++) { int status_reason; ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd; OCSP_SINGLERESP *single_response = OCSP_resp_get0(basic_response, i); if (!single_response) { goto clean_up; } ocsp_status = OCSP_single_get0_status(single_response, &status_reason, &revtime, &thisupd, &nextupd); uint64_t this_update = 0; int thisupd_err = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) thisupd->data, (uint32_t) thisupd->length, &this_update); uint64_t next_update = 0; int nextupd_err = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) nextupd->data, (uint32_t) nextupd->length, &next_update); uint64_t current_time = 0; int current_time_err = conn->config->wall_clock(conn->config->sys_clock_ctx, ¤t_time); if (thisupd_err || nextupd_err || current_time_err) { ret_val = S2N_CERT_ERR_UNTRUSTED; goto clean_up; } if (current_time < this_update || current_time > next_update) { ret_val = S2N_CERT_ERR_EXPIRED; goto clean_up; } switch (ocsp_status) { case V_OCSP_CERTSTATUS_GOOD: break; case V_OCSP_CERTSTATUS_REVOKED: ret_val = S2N_CERT_ERR_REVOKED; goto clean_up; case V_OCSP_CERTSTATUS_UNKNOWN: goto clean_up; default: goto clean_up; } } ret_val = S2N_CERT_OK; clean_up: if (basic_response) { OCSP_BASICRESP_free(basic_response); } if (ocsp_response) { OCSP_RESPONSE_free(ocsp_response); } return ret_val; #endif /* S2N_OCSP_STAPLING_SUPPORTED */ }