in ssl/handoff.cc [1029:1163]
int SSL_set_handshake_hints(SSL *ssl, const uint8_t *hints, size_t hints_len) {
if (SSL_is_dtls(ssl)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
UniquePtr<SSL_HANDSHAKE_HINTS> hints_obj = MakeUnique<SSL_HANDSHAKE_HINTS>();
if (hints_obj == nullptr) {
return 0;
}
CBS cbs, seq, server_random_tls13, key_share, signature_hint, psk,
cert_compression, server_random_tls12, ecdhe, ticket;
int has_server_random_tls13, has_key_share, has_signature_hint, has_psk,
has_cert_compression, has_server_random_tls12, has_ecdhe, has_ticket;
CBS_init(&cbs, hints, hints_len);
if (!CBS_get_asn1(&cbs, &seq, CBS_ASN1_SEQUENCE) ||
!CBS_get_optional_asn1(&seq, &server_random_tls13,
&has_server_random_tls13, kServerRandomTLS13Tag) ||
!CBS_get_optional_asn1(&seq, &key_share, &has_key_share,
kKeyShareHintTag) ||
!CBS_get_optional_asn1(&seq, &signature_hint, &has_signature_hint,
kSignatureHintTag) ||
!CBS_get_optional_asn1(&seq, &psk, &has_psk, kDecryptedPSKTag) ||
!get_optional_implicit_null(&seq, &hints_obj->ignore_psk,
kIgnorePSKTag) ||
!CBS_get_optional_asn1(&seq, &cert_compression, &has_cert_compression,
kCompressCertificateTag) ||
!CBS_get_optional_asn1(&seq, &server_random_tls12,
&has_server_random_tls12, kServerRandomTLS12Tag) ||
!CBS_get_optional_asn1(&seq, &ecdhe, &has_ecdhe, kECDHEHintTag) ||
!CBS_get_optional_asn1(&seq, &ticket, &has_ticket, kDecryptedTicketTag) ||
!get_optional_implicit_null(&seq, &hints_obj->renew_ticket,
kRenewTicketTag) ||
!get_optional_implicit_null(&seq, &hints_obj->ignore_ticket,
kIgnoreTicketTag)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
if (has_server_random_tls13 &&
!hints_obj->server_random_tls13.CopyFrom(server_random_tls13)) {
return 0;
}
if (has_key_share) {
uint64_t group_id;
CBS public_key, secret;
if (!CBS_get_asn1_uint64(&key_share, &group_id) || //
group_id == 0 || group_id > 0xffff ||
!CBS_get_asn1(&key_share, &public_key, CBS_ASN1_OCTETSTRING) ||
!hints_obj->key_share_public_key.CopyFrom(public_key) ||
!CBS_get_asn1(&key_share, &secret, CBS_ASN1_OCTETSTRING) ||
!hints_obj->key_share_secret.CopyFrom(secret)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
hints_obj->key_share_group_id = static_cast<uint16_t>(group_id);
}
if (has_signature_hint) {
uint64_t sig_alg;
CBS input, spki, signature;
if (!CBS_get_asn1_uint64(&signature_hint, &sig_alg) || //
sig_alg == 0 || sig_alg > 0xffff ||
!CBS_get_asn1(&signature_hint, &input, CBS_ASN1_OCTETSTRING) ||
!hints_obj->signature_input.CopyFrom(input) ||
!CBS_get_asn1(&signature_hint, &spki, CBS_ASN1_OCTETSTRING) ||
!hints_obj->signature_spki.CopyFrom(spki) ||
!CBS_get_asn1(&signature_hint, &signature, CBS_ASN1_OCTETSTRING) ||
!hints_obj->signature.CopyFrom(signature)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
hints_obj->signature_algorithm = static_cast<uint16_t>(sig_alg);
}
if (has_psk && !hints_obj->decrypted_psk.CopyFrom(psk)) {
return 0;
}
if (has_psk && hints_obj->ignore_psk) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
if (has_cert_compression) {
uint64_t alg;
CBS input, output;
if (!CBS_get_asn1_uint64(&cert_compression, &alg) || //
alg == 0 || alg > 0xffff ||
!CBS_get_asn1(&cert_compression, &input, CBS_ASN1_OCTETSTRING) ||
!hints_obj->cert_compression_input.CopyFrom(input) ||
!CBS_get_asn1(&cert_compression, &output, CBS_ASN1_OCTETSTRING) ||
!hints_obj->cert_compression_output.CopyFrom(output)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
hints_obj->cert_compression_alg_id = static_cast<uint16_t>(alg);
}
if (has_server_random_tls12 &&
!hints_obj->server_random_tls12.CopyFrom(server_random_tls12)) {
return 0;
}
if (has_ecdhe) {
uint64_t group_id;
CBS public_key, private_key;
if (!CBS_get_asn1_uint64(&ecdhe, &group_id) || //
group_id == 0 || group_id > 0xffff ||
!CBS_get_asn1(&ecdhe, &public_key, CBS_ASN1_OCTETSTRING) ||
!hints_obj->ecdhe_public_key.CopyFrom(public_key) ||
!CBS_get_asn1(&ecdhe, &private_key, CBS_ASN1_OCTETSTRING) ||
!hints_obj->ecdhe_private_key.CopyFrom(private_key)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
hints_obj->ecdhe_group_id = static_cast<uint16_t>(group_id);
}
if (has_ticket && !hints_obj->decrypted_ticket.CopyFrom(ticket)) {
return 0;
}
if (has_ticket && hints_obj->ignore_ticket) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
if (!has_ticket && hints_obj->renew_ticket) {
OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS);
return 0;
}
ssl->s3->hs->hints = std::move(hints_obj);
return 1;
}