static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL *ssl, SSL_HANDSHAKE *hs, int is_first_run) { /* Don't send CertificateVerify if there is no certificate. */ if (!ssl_has_certificate(ssl)) { hs->state = state_send_client_finished; return ssl_hs_ok; } switch (tls13_prepare_certificate_verify(ssl, is_first_run)) { case ssl_private_key_success: hs->state = state_send_client_finished; return ssl_hs_write_message; case ssl_private_key_retry: hs->state = state_complete_client_certificate_verify; return ssl_hs_private_key_operation; case ssl_private_key_failure: return ssl_hs_error; } assert(0); return ssl_hs_error; }
int ssl_add_cert_chain(SSL *ssl, CBB *cbb) { if (!ssl_has_certificate(ssl)) { return CBB_add_u24(cbb, 0); } CBB certs; if (!CBB_add_u24_length_prefixed(cbb, &certs)) { goto err; } STACK_OF(CRYPTO_BUFFER) *chain = ssl->cert->chain; for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain); i++) { CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(chain, i); CBB child; if (!CBB_add_u24_length_prefixed(&certs, &child) || !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer)) || !CBB_flush(&certs)) { goto err; } } return CBB_flush(cbb); err: OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; }
int ssl_on_certificate_selected(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; if (!ssl_has_certificate(ssl)) { /* Nothing to do. */ return 1; } if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(ssl)) { return 0; } CBS leaf; CRYPTO_BUFFER_init_CBS(sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0), &leaf); EVP_PKEY_free(hs->local_pubkey); hs->local_pubkey = ssl_cert_parse_pubkey(&leaf); return hs->local_pubkey != NULL; }
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; }
int tls13_prepare_certificate(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; CBB cbb, body, certificate_list; if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) || /* The request context is always empty in the handshake. */ !CBB_add_u8(&body, 0) || !CBB_add_u24_length_prefixed(&body, &certificate_list)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } if (!ssl_has_certificate(ssl)) { if (!ssl_complete_message(ssl, &cbb)) { goto err; } return 1; } CERT *cert = ssl->cert; CBB leaf, extensions; if (!CBB_add_u24_length_prefixed(&certificate_list, &leaf) || !ssl_add_cert_to_cbb(&leaf, cert->x509_leaf) || !CBB_add_u16_length_prefixed(&certificate_list, &extensions)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } if (hs->scts_requested && ssl->ctx->signed_cert_timestamp_list_length != 0) { CBB contents; if (!CBB_add_u16(&extensions, TLSEXT_TYPE_certificate_timestamp) || !CBB_add_u16_length_prefixed(&extensions, &contents) || !CBB_add_bytes(&contents, ssl->ctx->signed_cert_timestamp_list, ssl->ctx->signed_cert_timestamp_list_length) || !CBB_flush(&extensions)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } } if (hs->ocsp_stapling_requested && ssl->ocsp_response != NULL) { CBB contents, ocsp_response; if (!CBB_add_u16(&extensions, TLSEXT_TYPE_status_request) || !CBB_add_u16_length_prefixed(&extensions, &contents) || !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) || !CBB_add_u24_length_prefixed(&contents, &ocsp_response) || !CBB_add_bytes(&ocsp_response, CRYPTO_BUFFER_data(ssl->ocsp_response), CRYPTO_BUFFER_len(ssl->ocsp_response)) || !CBB_flush(&extensions)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } } for (size_t i = 0; i < sk_X509_num(cert->x509_chain); i++) { CBB child; if (!CBB_add_u24_length_prefixed(&certificate_list, &child) || !ssl_add_cert_to_cbb(&child, sk_X509_value(cert->x509_chain, i)) || !CBB_add_u16(&certificate_list, 0 /* no extensions */)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); goto err; } } if (!ssl_complete_message(ssl, &cbb)) { goto err; } return 1; err: CBB_cleanup(&cbb); return 0; }
static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; /* Send a ServerHello. */ CBB cbb, body, extensions; if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) || !CBB_add_u16(&body, ssl->version) || !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) || !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) || !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) || !CBB_add_u16_length_prefixed(&body, &extensions) || !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || !ssl_ext_key_share_add_serverhello(hs, &extensions)) { goto err; } if (ssl->s3->short_header) { if (!CBB_add_u16(&extensions, TLSEXT_TYPE_short_header) || !CBB_add_u16(&extensions, 0 /* empty extension */)) { goto err; } } if (!ssl_add_message_cbb(ssl, &cbb)) { goto err; } /* Derive and enable the handshake traffic secrets. */ if (!tls13_derive_handshake_secrets(hs) || !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret, hs->hash_len) || !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret, hs->hash_len)) { goto err; } /* Send EncryptedExtensions. */ if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_ENCRYPTED_EXTENSIONS) || !ssl_add_serverhello_tlsext(hs, &body) || !ssl_add_message_cbb(ssl, &cbb)) { goto err; } /* Determine whether to request a client certificate. */ hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER); /* CertificateRequest may only be sent in non-resumption handshakes. */ if (ssl->s3->session_reused) { hs->cert_request = 0; } /* Send a CertificateRequest, if necessary. */ if (hs->cert_request) { CBB 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 num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs); if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) { goto err; } for (size_t i = 0; i < num_sigalgs; 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_add_message_cbb(ssl, &cbb)) { goto err; } } /* Send the server Certificate message, if necessary. */ if (!ssl->s3->session_reused) { if (!ssl_has_certificate(ssl)) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET); goto err; } if (!tls13_add_certificate(hs)) { goto err; } hs->tls13_state = state_send_server_certificate_verify; return ssl_hs_ok; } hs->tls13_state = state_send_server_finished; return ssl_hs_ok; err: CBB_cleanup(&cbb); return ssl_hs_error; }