static enum ssl_hs_wait_t do_process_certificate_request(SSL *ssl, SSL_HANDSHAKE *hs) { ssl->s3->tmp.cert_request = 0; /* CertificateRequest may only be sent in certificate-based ciphers. */ if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { hs->state = state_process_server_finished; return ssl_hs_ok; } /* CertificateRequest is optional. */ if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) { hs->state = state_process_server_certificate; return ssl_hs_ok; } CBS cbs, context, supported_signature_algorithms; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u8_length_prefixed(&cbs, &context) || /* The request context is always empty during the handshake. */ CBS_len(&context) != 0 || !CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) || CBS_len(&supported_signature_algorithms) == 0 || !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return ssl_hs_error; } uint8_t alert; STACK_OF(X509_NAME) *ca_sk = ssl_parse_client_CA_list(ssl, &alert, &cbs); if (ca_sk == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } /* Ignore extensions. */ CBS extensions; if (!CBS_get_u16_length_prefixed(&cbs, &extensions) || CBS_len(&cbs) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return ssl_hs_error; } ssl->s3->tmp.cert_request = 1; sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free); ssl->s3->tmp.ca_names = ca_sk; if (!ssl->method->hash_current_message(ssl)) { return ssl_hs_error; } hs->state = state_process_server_certificate; return ssl_hs_read_message; }
static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl, SSL_HANDSHAKE *hs) { /* Determine whether to request a client certificate. */ ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER); /* CertificateRequest may only be sent in certificate-based ciphers. */ if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { ssl->s3->tmp.cert_request = 0; } if (!ssl->s3->tmp.cert_request) { /* Skip this state. */ hs->state = state_send_server_certificate; return ssl_hs_ok; } CBB cbb, body, sigalgs_cbb; if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE_REQUEST) || !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) { goto err; } const uint16_t *sigalgs; size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs); if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) { goto err; } for (size_t i = 0; i < sigalgs_len; i++) { if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) { goto err; } } if (!ssl_add_client_CA_list(ssl, &body) || !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) || !ssl->method->finish_message(ssl, &cbb)) { goto err; } hs->state = state_send_server_certificate; return ssl_hs_write_message; err: CBB_cleanup(&cbb); return ssl_hs_error; }
static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl, SSL_HANDSHAKE *hs) { if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) { hs->state = state_send_server_finished; return ssl_hs_ok; } if (!ssl_has_certificate(ssl)) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET); return ssl_hs_error; } if (!tls13_prepare_certificate(ssl)) { return ssl_hs_error; } hs->state = state_send_server_certificate_verify; return ssl_hs_write_message; }