int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) { SSL *const ssl = hs->ssl; CBS cbs, context, certificate_list; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u8_length_prefixed(&cbs, &context) || CBS_len(&context) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return 0; } const int retain_sha256 = ssl->server && ssl->retain_only_sha256_of_client_certs; int ret = 0; EVP_PKEY *pkey = NULL; STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null(); if (certs == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } while (CBS_len(&certificate_list) > 0) { CBS certificate, extensions; if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) || !CBS_get_u16_length_prefixed(&certificate_list, &extensions) || CBS_len(&certificate) == 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 0) { pkey = ssl_cert_parse_pubkey(&certificate); if (pkey == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } /* TLS 1.3 always uses certificate keys for signing thus the correct * keyUsage is enforced. */ if (!ssl_cert_check_digital_signature_key_usage(&certificate)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); goto err; } if (retain_sha256) { /* Retain the hash of the leaf certificate if requested. */ SHA256(CBS_data(&certificate), CBS_len(&certificate), ssl->s3->new_session->peer_sha256); } } CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool); if (buf == NULL || !sk_CRYPTO_BUFFER_push(certs, buf)) { CRYPTO_BUFFER_free(buf); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* Parse out the extensions. */ int have_status_request = 0, have_sct = 0; CBS status_request, sct; const SSL_EXTENSION_TYPE ext_types[] = { {TLSEXT_TYPE_status_request, &have_status_request, &status_request}, {TLSEXT_TYPE_certificate_timestamp, &have_sct, &sct}, }; uint8_t alert; if (!ssl_parse_extensions(&extensions, &alert, ext_types, OPENSSL_ARRAY_SIZE(ext_types), 0 /* reject unknown */)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); goto err; } /* All Certificate extensions are parsed, but only the leaf extensions are * stored. */ if (have_status_request) { if (ssl->server || !ssl->ocsp_stapling_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } uint8_t status_type; CBS ocsp_response; if (!CBS_get_u8(&status_request, &status_type) || status_type != TLSEXT_STATUSTYPE_ocsp || !CBS_get_u24_length_prefixed(&status_request, &ocsp_response) || CBS_len(&ocsp_response) == 0 || CBS_len(&status_request) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&ocsp_response, &ssl->s3->new_session->ocsp_response, &ssl->s3->new_session->ocsp_response_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } if (have_sct) { if (ssl->server || !ssl->signed_cert_timestamps_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } if (!ssl_is_sct_list_valid(&sct)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&sct, &ssl->s3->new_session->tlsext_signed_cert_timestamp_list, &ssl->s3->new_session ->tlsext_signed_cert_timestamp_list_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } } if (CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } EVP_PKEY_free(hs->peer_pubkey); hs->peer_pubkey = pkey; pkey = NULL; sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free); ssl->s3->new_session->certs = certs; certs = NULL; if (!ssl_session_x509_cache_objects(ssl->s3->new_session)) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) { if (!allow_anonymous) { OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED); goto err; } /* OpenSSL returns X509_V_OK when no certificates are requested. This is * classed by them as a bug, but it's assumed by at least NGINX. */ ssl->s3->new_session->verify_result = X509_V_OK; /* No certificate, so nothing more to do. */ ret = 1; goto err; } ssl->s3->new_session->peer_sha256_valid = retain_sha256; if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result, ssl->s3->new_session->x509_chain)) { goto err; } ret = 1; err: sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free); EVP_PKEY_free(pkey); return ret; }
int tls13_process_certificate(SSL *ssl) { CBS cbs, context; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u8_length_prefixed(&cbs, &context) || CBS_len(&context) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return 0; } int ret = 0; uint8_t alert; STACK_OF(X509) *chain = ssl_parse_cert_chain( ssl, &alert, ssl->ctx->retain_only_sha256_of_client_certs ? ssl->s3->new_session->peer_sha256 : NULL, &cbs); if (chain == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); goto err; } if (CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_X509_num(chain) == 0) { /* Clients must receive a certificate from the server. */ if (!ssl->server) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } /* Servers may be configured to accept anonymous clients. */ if ((ssl->verify_mode & SSL_VERIFY_PEER) && (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); goto err; } /* No certificate, so nothing more to do. */ ret = 1; goto err; } if (ssl->server && ssl->ctx->retain_only_sha256_of_client_certs) { /* The hash was filled in by |ssl_parse_cert_chain|. */ ssl->s3->new_session->peer_sha256_valid = 1; } X509 *leaf = sk_X509_value(chain, 0); if (!ssl->server && !ssl_check_leaf_certificate(ssl, leaf)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); goto err; } int verify_ret = ssl_verify_cert_chain(ssl, chain); /* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */ if (ssl->verify_mode != SSL_VERIFY_NONE && verify_ret <= 0) { int al = ssl_verify_alarm_type(ssl->verify_result); ssl3_send_alert(ssl, SSL3_AL_FATAL, al); OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED); goto err; } ERR_clear_error(); ssl->s3->new_session->verify_result = ssl->verify_result; X509_free(ssl->s3->new_session->peer); /* For historical reasons, the client and server differ on whether the chain * includes the leaf. */ if (ssl->server) { ssl->s3->new_session->peer = sk_X509_shift(chain); } else { ssl->s3->new_session->peer = X509_up_ref(leaf); } sk_X509_pop_free(ssl->s3->new_session->cert_chain, X509_free); ssl->s3->new_session->cert_chain = chain; chain = NULL; ret = 1; err: sk_X509_pop_free(chain, X509_free); return ret; }
/* loads in the certificate from the server */ int ssl2_set_certificate(SSL *s, int type, int len, const unsigned char *data) { STACK_OF(X509) *sk=NULL; EVP_PKEY *pkey=NULL; SESS_CERT *sc=NULL; int i; X509 *x509=NULL; int ret=0; x509=d2i_X509(NULL,&data,(long)len); if (x509 == NULL) { SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_X509_LIB); goto err; } if ((sk=sk_X509_new_null()) == NULL || !sk_X509_push(sk,x509)) { SSLerr(SSL_F_SSL2_SET_CERTIFICATE,ERR_R_MALLOC_FAILURE); goto err; } i=ssl_verify_cert_chain(s,sk); if ((s->verify_mode != SSL_VERIFY_NONE) && (!i)) { SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); goto err; } ERR_clear_error(); /* but we keep s->verify_result */ s->session->verify_result = s->verify_result; /* server's cert for this session */ sc=ssl_sess_cert_new(); if (sc == NULL) { ret= -1; goto err; } if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert); s->session->sess_cert=sc; sc->peer_pkeys[SSL_PKEY_RSA_ENC].x509=x509; sc->peer_key= &(sc->peer_pkeys[SSL_PKEY_RSA_ENC]); pkey=X509_get_pubkey(x509); x509=NULL; if (pkey == NULL) { SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY); goto err; } if (pkey->type != EVP_PKEY_RSA) { SSLerr(SSL_F_SSL2_SET_CERTIFICATE,SSL_R_PUBLIC_KEY_NOT_RSA); goto err; } if (!ssl_set_peer_cert_type(sc,SSL2_CT_X509_CERTIFICATE)) goto err; ret=1; err: sk_X509_free(sk); X509_free(x509); EVP_PKEY_free(pkey); return(ret); }
int tls13_process_certificate(SSL *ssl, int allow_anonymous) { CBS cbs, context; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u8_length_prefixed(&cbs, &context) || CBS_len(&context) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return 0; } const int retain_sha256 = ssl->server && ssl->ctx->retain_only_sha256_of_client_certs; int ret = 0; uint8_t alert; STACK_OF(X509) *chain = ssl_parse_cert_chain( ssl, &alert, retain_sha256 ? ssl->s3->new_session->peer_sha256 : NULL, &cbs); if (chain == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); goto err; } if (CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_X509_num(chain) == 0) { if (!allow_anonymous) { OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED); goto err; } /* OpenSSL returns X509_V_OK when no certificates are requested. This is * classed by them as a bug, but it's assumed by at least NGINX. */ ssl->s3->new_session->verify_result = X509_V_OK; /* No certificate, so nothing more to do. */ ret = 1; goto err; } ssl->s3->new_session->peer_sha256_valid = retain_sha256; if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result, chain)) { goto err; } X509_free(ssl->s3->new_session->peer); X509 *leaf = sk_X509_value(chain, 0); X509_up_ref(leaf); ssl->s3->new_session->peer = leaf; sk_X509_pop_free(ssl->s3->new_session->cert_chain, X509_free); ssl->s3->new_session->cert_chain = chain; chain = NULL; ret = 1; err: sk_X509_pop_free(chain, X509_free); return ret; }