/* * (C) 2022 Jack Lloyd * (C) 2022 Hannes Rantzsch, René Meusel - neXenio GmbH * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #include namespace Botan::TLS { Handshake_Type Certificate_Request_13::type() const { return TLS::Handshake_Type::CertificateRequest; } Certificate_Request_13::Certificate_Request_13(const std::vector& buf, const Connection_Side side) { TLS_Data_Reader reader("Certificate_Request_13", buf); // RFC 8446 4.3.2 // A server which is authenticating with a certificate MAY optionally // request a certificate from the client. if(side != Connection_Side::Server) { throw TLS_Exception(Alert::UnexpectedMessage, "Received a Certificate_Request message from a client"); } m_context = reader.get_tls_length_value(1); m_extensions.deserialize(reader, side, type()); // RFC 8446 4.3.2 // The "signature_algorithms" extension MUST be specified, and other // extensions may optionally be included if defined for this message. // Clients MUST ignore unrecognized extensions. if(!m_extensions.has()) { throw TLS_Exception(Alert::MissingExtension, "Certificate_Request message did not provide a signature_algorithms extension"); } // RFC 8446 4.2. // The table below indicates the messages where a given extension may // appear [...]. If an implementation receives an extension which it // recognizes and which is not specified for the message in which it // appears, it MUST abort the handshake with an "illegal_parameter" alert. // // For Certificate Request said table states: // "status_request", "signature_algorithms", "signed_certificate_timestamp", // "certificate_authorities", "oid_filters", "signature_algorithms_cert", std::set allowed_extensions = { Extension_Code::CertificateStatusRequest, Extension_Code::SignatureAlgorithms, // Extension_Code::SignedCertificateTimestamp, // NYI Extension_Code::CertificateAuthorities, // Extension_Code::OidFilters, // NYI Extension_Code::CertSignatureAlgorithms, }; if(m_extensions.contains_implemented_extensions_other_than(allowed_extensions)) { throw TLS_Exception(Alert::IllegalParameter, "Certificate Request contained an extension that is not allowed"); } } Certificate_Request_13::Certificate_Request_13(std::vector acceptable_CAs, const Policy& policy, Callbacks& callbacks) { // RFC 8446 4.3.2 // The certificate_request_context [here: m_context] MUST be unique within // the scope of this connection (thus preventing replay of client // CertificateVerify messages). This field SHALL be zero length unless // used for the post-handshake authentication exchanges described in // Section 4.6.2. // // TODO: Post-Handshake auth must fill m_context in an unpredictable way // RFC 8446 4.3.2 // [Supported signature algorithms are] expressed by sending the // "signature_algorithms" and optionally "signature_algorithms_cert" // extensions. [A list of certificate authorities which the server would // accept] is expressed by sending the "certificate_authorities" extension. // // The "signature_algorithms" extension MUST be specified, and other // extensions may optionally be included if defined for this message. m_extensions.add(std::make_unique(policy.acceptable_signature_schemes())); if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) { // RFC 8446 4.2.3 // Implementations which have the same policy in both cases MAY omit // the "signature_algorithms_cert" extension. m_extensions.add(std::make_unique(std::move(cert_signing_prefs.value()))); } if(!acceptable_CAs.empty()) { m_extensions.add(std::make_unique(std::move(acceptable_CAs))); } // TODO: Support cert_status_request for OCSP stapling callbacks.tls_modify_extensions(m_extensions, Connection_Side::Server, type()); } std::optional Certificate_Request_13::maybe_create(const Client_Hello_13& client_hello, Credentials_Manager& cred_mgr, Callbacks& callbacks, const Policy& policy) { const auto trusted_CAs = cred_mgr.trusted_certificate_authorities("tls-server", client_hello.sni_hostname()); std::vector client_auth_CAs; for(const auto store : trusted_CAs) { const auto subjects = store->all_subjects(); client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); } if(client_auth_CAs.empty() && !policy.request_client_certificate_authentication()) { return std::nullopt; } return Certificate_Request_13(std::move(client_auth_CAs), policy, callbacks); } std::vector Certificate_Request_13::acceptable_CAs() const { if(m_extensions.has()) { return m_extensions.get()->distinguished_names(); } return {}; } const std::vector& Certificate_Request_13::signature_schemes() const { // RFC 8446 4.3.2 // The "signature_algorithms" extension MUST be specified BOTAN_ASSERT_NOMSG(m_extensions.has()); return m_extensions.get()->supported_schemes(); } const std::vector& Certificate_Request_13::certificate_signature_schemes() const { // RFC 8446 4.2.3 // If no "signature_algorithms_cert" extension is present, then the // "signature_algorithms" extension also applies to signatures appearing // in certificates. if(auto sig_schemes_cert = m_extensions.get()) { return sig_schemes_cert->supported_schemes(); } else { return signature_schemes(); } } std::vector Certificate_Request_13::serialize() const { std::vector buf; append_tls_length_value(buf, m_context, 1); buf += m_extensions.serialize(Connection_Side::Server); return buf; } } // namespace Botan::TLS