2021-05-18 21:55:06 +02:00
/*
* Copyright ( c ) 2020 , Ali Mohammad Pur < mpfard @ serenityos . org >
2022-02-17 19:43:42 +01:00
* Copyright ( c ) 2022 , Michiel Visser < opensource @ webmichiel . nl >
2021-05-18 21:55:06 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <AK/Debug.h>
# include <AK/Endian.h>
# include <AK/Random.h>
# include <LibCore/Timer.h>
# include <LibCrypto/ASN1/DER.h>
2022-03-20 21:20:04 +01:00
# include <LibCrypto/Curves/Ed25519.h>
2022-03-05 18:13:39 +01:00
# include <LibCrypto/Curves/EllipticCurve.h>
2023-11-15 19:56:29 +01:00
# include <LibCrypto/Curves/SECPxxxr1.h>
2022-03-05 18:13:39 +01:00
# include <LibCrypto/Curves/X25519.h>
# include <LibCrypto/Curves/X448.h>
2022-02-18 10:58:56 +01:00
# include <LibCrypto/PK/Code/EMSA_PKCS1_V1_5.h>
2021-05-18 21:55:06 +02:00
# include <LibTLS/TLSv12.h>
namespace TLS {
ssize_t TLSv12 : : handle_server_hello ( ReadonlyBytes buffer , WritePacketStage & write_packets )
{
write_packets = WritePacketStage : : Initial ;
if ( m_context . connection_status ! = ConnectionStatus : : Disconnected & & m_context . connection_status ! = ConnectionStatus : : Renegotiating ) {
dbgln ( " unexpected hello message " ) ;
return ( i8 ) Error : : UnexpectedMessage ;
}
ssize_t res = 0 ;
size_t min_hello_size = 41 ;
if ( min_hello_size > buffer . size ( ) ) {
dbgln ( " need more data " ) ;
return ( i8 ) Error : : NeedMoreData ;
}
size_t following_bytes = buffer [ 0 ] * 0x10000 + buffer [ 1 ] * 0x100 + buffer [ 2 ] ;
res + = 3 ;
if ( buffer . size ( ) - res < following_bytes ) {
dbgln ( " not enough data after header: {} < {} " , buffer . size ( ) - res , following_bytes ) ;
return ( i8 ) Error : : NeedMoreData ;
}
if ( buffer . size ( ) - res < 2 ) {
dbgln ( " not enough data for version " ) ;
return ( i8 ) Error : : NeedMoreData ;
}
2023-04-13 23:53:22 +02:00
auto version = static_cast < ProtocolVersion > ( AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res ) ) ) ) ;
2021-05-18 21:55:06 +02:00
res + = 2 ;
if ( ! supports_version ( version ) )
return ( i8 ) Error : : NotSafe ;
memcpy ( m_context . remote_random , buffer . offset_pointer ( res ) , sizeof ( m_context . remote_random ) ) ;
res + = sizeof ( m_context . remote_random ) ;
u8 session_length = buffer [ res + + ] ;
if ( buffer . size ( ) - res < session_length ) {
dbgln ( " not enough data for session id " ) ;
return ( i8 ) Error : : NeedMoreData ;
}
if ( session_length & & session_length < = 32 ) {
memcpy ( m_context . session_id , buffer . offset_pointer ( res ) , session_length ) ;
m_context . session_id_size = session_length ;
if constexpr ( TLS_DEBUG ) {
dbgln ( " Remote session ID: " ) ;
print_buffer ( ReadonlyBytes { m_context . session_id , session_length } ) ;
}
} else {
m_context . session_id_size = 0 ;
}
res + = session_length ;
if ( buffer . size ( ) - res < 2 ) {
dbgln ( " not enough data for cipher suite listing " ) ;
return ( i8 ) Error : : NeedMoreData ;
}
auto cipher = static_cast < CipherSuite > ( AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res ) ) ) ) ;
res + = 2 ;
if ( ! supports_cipher ( cipher ) ) {
2023-04-14 00:22:24 +02:00
m_context . cipher = CipherSuite : : TLS_NULL_WITH_NULL_NULL ;
2021-05-18 21:55:06 +02:00
dbgln ( " No supported cipher could be agreed upon " ) ;
return ( i8 ) Error : : NoCommonCipher ;
}
m_context . cipher = cipher ;
2023-04-14 00:45:32 +02:00
dbgln_if ( TLS_DEBUG , " Cipher: {} " , enum_to_string ( cipher ) ) ;
2021-05-18 21:55:06 +02:00
2021-05-29 08:26:10 +02:00
// Simplification: We only support handshake hash functions via HMAC
m_context . handshake_hash . initialize ( hmac_hash ( ) ) ;
2021-05-18 21:55:06 +02:00
// Compression method
if ( buffer . size ( ) - res < 1 )
return ( i8 ) Error : : NeedMoreData ;
u8 compression = buffer [ res + + ] ;
if ( compression ! = 0 )
return ( i8 ) Error : : CompressionNotSupported ;
if ( m_context . connection_status ! = ConnectionStatus : : Renegotiating )
m_context . connection_status = ConnectionStatus : : Negotiating ;
if ( m_context . is_server ) {
dbgln ( " unsupported: server mode " ) ;
write_packets = WritePacketStage : : ServerHandshake ;
}
// Presence of extensions is determined by availability of bytes after compression_method
if ( buffer . size ( ) - res > = 2 ) {
auto extensions_bytes_total = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res + = 2 ) ) ) ;
dbgln_if ( TLS_DEBUG , " Extensions bytes total: {} " , extensions_bytes_total ) ;
}
while ( buffer . size ( ) - res > = 4 ) {
2023-04-14 00:07:17 +02:00
auto extension_type = ( ExtensionType ) AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res ) ) ) ;
2021-05-18 21:55:06 +02:00
res + = 2 ;
u16 extension_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res ) ) ) ;
res + = 2 ;
2023-04-14 00:45:32 +02:00
dbgln_if ( TLS_DEBUG , " Extension {} with length {} " , enum_to_string ( extension_type ) , extension_length ) ;
2021-05-18 21:55:06 +02:00
if ( buffer . size ( ) - res < extension_length )
return ( i8 ) Error : : NeedMoreData ;
2023-04-14 00:07:17 +02:00
if ( extension_type = = ExtensionType : : SERVER_NAME ) {
2021-05-18 21:55:06 +02:00
// RFC6066 section 3: SNI extension_data can be empty in the server hello
if ( extension_length > 0 ) {
// ServerNameList total size
if ( buffer . size ( ) - res < 2 )
return ( i8 ) Error : : NeedMoreData ;
auto sni_name_list_bytes = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res + = 2 ) ) ) ;
dbgln_if ( TLS_DEBUG , " SNI: expecting ServerNameList of {} bytes " , sni_name_list_bytes ) ;
// Exactly one ServerName should be present
if ( buffer . size ( ) - res < 3 )
return ( i8 ) Error : : NeedMoreData ;
2022-04-01 20:58:27 +03:00
auto sni_name_type = ( NameType ) ( * ( u8 const * ) buffer . offset_pointer ( res + + ) ) ;
2021-05-18 21:55:06 +02:00
auto sni_name_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res + = 2 ) ) ) ;
2023-04-14 00:10:16 +02:00
if ( sni_name_type ! = NameType : : HOST_NAME )
2021-05-18 21:55:06 +02:00
return ( i8 ) Error : : NotUnderstood ;
if ( sizeof ( sni_name_type ) + sizeof ( sni_name_length ) + sni_name_length ! = sni_name_list_bytes )
return ( i8 ) Error : : BrokenPacket ;
// Read out the host_name
if ( buffer . size ( ) - res < sni_name_length )
return ( i8 ) Error : : NeedMoreData ;
2023-12-16 17:49:34 +03:30
m_context . extensions . SNI = ByteString { ( char const * ) buffer . offset_pointer ( res ) , sni_name_length } ;
2021-05-18 21:55:06 +02:00
res + = sni_name_length ;
dbgln ( " SNI host_name: {} " , m_context . extensions . SNI ) ;
}
2023-04-14 00:07:17 +02:00
} else if ( extension_type = = ExtensionType : : APPLICATION_LAYER_PROTOCOL_NEGOTIATION & & m_context . alpn . size ( ) ) {
2021-05-18 21:55:06 +02:00
if ( buffer . size ( ) - res > 2 ) {
auto alpn_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( res ) ) ) ;
if ( alpn_length & & alpn_length < = extension_length - 2 ) {
2022-04-01 20:58:27 +03:00
u8 const * alpn = buffer . offset_pointer ( res + 2 ) ;
2021-05-18 21:55:06 +02:00
size_t alpn_position = 0 ;
while ( alpn_position < alpn_length ) {
u8 alpn_size = alpn [ alpn_position + + ] ;
if ( alpn_size + alpn_position > = extension_length )
break ;
2023-12-16 17:49:34 +03:30
ByteString alpn_str { ( char const * ) alpn + alpn_position , alpn_length } ;
2021-05-18 21:55:06 +02:00
if ( alpn_size & & m_context . alpn . contains_slow ( alpn_str ) ) {
m_context . negotiated_alpn = alpn_str ;
dbgln ( " negotiated alpn: {} " , alpn_str ) ;
break ;
}
alpn_position + = alpn_length ;
if ( ! m_context . is_server ) // server hello must contain one ALPN
break ;
}
}
}
res + = extension_length ;
2023-04-14 00:07:17 +02:00
} else if ( extension_type = = ExtensionType : : SIGNATURE_ALGORITHMS ) {
2021-05-18 21:55:06 +02:00
dbgln ( " supported signatures: " ) ;
print_buffer ( buffer . slice ( res , extension_length ) ) ;
res + = extension_length ;
// FIXME: what are we supposed to do here?
2023-04-14 00:07:17 +02:00
} else if ( extension_type = = ExtensionType : : EC_POINT_FORMATS ) {
2022-02-17 19:43:42 +01:00
// RFC8422 section 5.2: A server that selects an ECC cipher suite in response to a ClientHello message
// including a Supported Point Formats Extension appends this extension (along with others) to its
// ServerHello message, enumerating the point formats it can parse. The Supported Point Formats Extension,
// when used, MUST contain the value 0 (uncompressed) as one of the items in the list of point formats.
//
// The current implementation only supports uncompressed points, and the server is required to support
// uncompressed points. Therefore, this extension can be safely ignored as it should always inform us
// that the server supports uncompressed points.
res + = extension_length ;
2023-11-25 00:27:45 +01:00
} else if ( extension_type = = ExtensionType : : EXTENDED_MASTER_SECRET ) {
m_context . extensions . extended_master_secret = true ;
res + = extension_length ;
2021-05-18 21:55:06 +02:00
} else {
2023-04-14 00:45:32 +02:00
dbgln ( " Encountered unknown extension {} with length {} " , enum_to_string ( extension_type ) , extension_length ) ;
2021-05-18 21:55:06 +02:00
res + = extension_length ;
}
}
return res ;
}
ssize_t TLSv12 : : handle_server_hello_done ( ReadonlyBytes buffer )
{
if ( buffer . size ( ) < 3 )
return ( i8 ) Error : : NeedMoreData ;
size_t size = buffer [ 0 ] * 0x10000 + buffer [ 1 ] * 0x100 + buffer [ 2 ] ;
if ( buffer . size ( ) - 3 < size )
return ( i8 ) Error : : NeedMoreData ;
return size + 3 ;
}
ByteBuffer TLSv12 : : build_server_key_exchange ( )
{
dbgln ( " FIXME: build_server_key_exchange " ) ;
return { } ;
}
2021-08-12 15:25:47 -04:00
ssize_t TLSv12 : : handle_server_key_exchange ( ReadonlyBytes buffer )
2021-05-18 21:55:06 +02:00
{
2021-05-29 07:29:56 +02:00
switch ( get_key_exchange_algorithm ( m_context . cipher ) ) {
case KeyExchangeAlgorithm : : RSA :
case KeyExchangeAlgorithm : : DH_DSS :
case KeyExchangeAlgorithm : : DH_RSA :
2021-05-19 00:12:09 +02:00
// RFC 5246 section 7.4.3. Server Key Exchange Message
// It is not legal to send the server key exchange message for RSA, DH_DSS, DH_RSA
2021-05-29 07:29:56 +02:00
dbgln ( " Server key exchange received for RSA, DH_DSS or DH_RSA is not legal " ) ;
2021-05-19 00:12:09 +02:00
return ( i8 ) Error : : UnexpectedMessage ;
2021-05-29 07:29:56 +02:00
case KeyExchangeAlgorithm : : DHE_DSS :
dbgln ( " Server key exchange for DHE_DSS is not implemented " ) ;
TODO ( ) ;
break ;
case KeyExchangeAlgorithm : : DHE_RSA :
2022-02-18 15:58:27 +01:00
return handle_dhe_rsa_server_key_exchange ( buffer ) ;
2021-05-29 07:29:56 +02:00
case KeyExchangeAlgorithm : : DH_anon :
dbgln ( " Server key exchange for DH_anon is not implemented " ) ;
TODO ( ) ;
break ;
case KeyExchangeAlgorithm : : ECDHE_RSA :
2022-02-17 19:43:42 +01:00
return handle_ecdhe_rsa_server_key_exchange ( buffer ) ;
2022-03-20 21:20:04 +01:00
case KeyExchangeAlgorithm : : ECDHE_ECDSA :
return handle_ecdhe_ecdsa_server_key_exchange ( buffer ) ;
2021-05-29 07:29:56 +02:00
case KeyExchangeAlgorithm : : ECDH_ECDSA :
case KeyExchangeAlgorithm : : ECDH_RSA :
case KeyExchangeAlgorithm : : ECDH_anon :
dbgln ( " Server key exchange for ECDHE algorithms is not implemented " ) ;
2021-05-19 00:12:09 +02:00
TODO ( ) ;
break ;
default :
2021-09-30 20:03:41 -04:00
dbgln ( " Unknown server key exchange algorithm " ) ;
2021-05-19 00:12:09 +02:00
VERIFY_NOT_REACHED ( ) ;
break ;
}
2021-05-18 21:55:06 +02:00
return 0 ;
}
2021-08-12 15:25:47 -04:00
ssize_t TLSv12 : : handle_dhe_rsa_server_key_exchange ( ReadonlyBytes buffer )
{
auto dh_p_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( 3 ) ) ) ;
auto dh_p = buffer . slice ( 5 , dh_p_length ) ;
2021-09-06 03:29:52 +04:30
auto p_result = ByteBuffer : : copy ( dh_p ) ;
2022-01-20 17:47:39 +00:00
if ( p_result . is_error ( ) ) {
2021-09-06 03:29:52 +04:30
dbgln ( " dhe_rsa_server_key_exchange failed: Not enough memory " ) ;
2022-02-18 15:58:27 +01:00
return ( i8 ) Error : : OutOfMemory ;
2021-09-06 03:29:52 +04:30
}
m_context . server_diffie_hellman_params . p = p_result . release_value ( ) ;
2021-08-12 15:25:47 -04:00
auto dh_g_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( 5 + dh_p_length ) ) ) ;
auto dh_g = buffer . slice ( 7 + dh_p_length , dh_g_length ) ;
2021-09-06 03:29:52 +04:30
auto g_result = ByteBuffer : : copy ( dh_g ) ;
2022-01-20 17:47:39 +00:00
if ( g_result . is_error ( ) ) {
2021-09-06 03:29:52 +04:30
dbgln ( " dhe_rsa_server_key_exchange failed: Not enough memory " ) ;
2022-02-18 15:58:27 +01:00
return ( i8 ) Error : : OutOfMemory ;
2021-09-06 03:29:52 +04:30
}
m_context . server_diffie_hellman_params . g = g_result . release_value ( ) ;
2021-08-12 15:25:47 -04:00
auto dh_Ys_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( 7 + dh_p_length + dh_g_length ) ) ) ;
auto dh_Ys = buffer . slice ( 9 + dh_p_length + dh_g_length , dh_Ys_length ) ;
2021-09-06 03:29:52 +04:30
auto Ys_result = ByteBuffer : : copy ( dh_Ys ) ;
2022-01-20 17:47:39 +00:00
if ( Ys_result . is_error ( ) ) {
2021-09-06 03:29:52 +04:30
dbgln ( " dhe_rsa_server_key_exchange failed: Not enough memory " ) ;
2022-02-18 15:58:27 +01:00
return ( i8 ) Error : : OutOfMemory ;
2021-09-06 03:29:52 +04:30
}
m_context . server_diffie_hellman_params . Ys = Ys_result . release_value ( ) ;
2021-08-12 15:25:47 -04:00
if constexpr ( TLS_DEBUG ) {
dbgln ( " dh_p: {:hex-dump} " , dh_p ) ;
dbgln ( " dh_g: {:hex-dump} " , dh_g ) ;
dbgln ( " dh_Ys: {:hex-dump} " , dh_Ys ) ;
}
2022-02-18 10:58:56 +01:00
auto server_key_info = buffer . slice ( 3 , 6 + dh_p_length + dh_g_length + dh_Ys_length ) ;
auto signature = buffer . slice ( 9 + dh_p_length + dh_g_length + dh_Ys_length ) ;
return verify_rsa_server_key_exchange ( server_key_info , signature ) ;
2021-08-12 15:25:47 -04:00
}
2022-03-20 21:20:04 +01:00
ssize_t TLSv12 : : handle_ecdhe_server_key_exchange ( ReadonlyBytes buffer , u8 & server_public_key_length )
2022-02-17 19:43:42 +01:00
{
2022-03-05 18:13:39 +01:00
if ( buffer . size ( ) < 7 )
2022-02-17 19:43:42 +01:00
return ( i8 ) Error : : NeedMoreData ;
auto curve_type = buffer [ 3 ] ;
2023-04-14 00:11:40 +02:00
if ( curve_type ! = ( u8 ) ECCurveType : : NAMED_CURVE )
2022-02-18 15:59:04 +01:00
return ( i8 ) Error : : NotUnderstood ;
2022-02-17 19:43:42 +01:00
2023-04-14 00:16:18 +02:00
auto curve = static_cast < SupportedGroup > ( AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( buffer . offset_pointer ( 4 ) ) ) ) ;
2022-02-18 17:43:50 +01:00
if ( ! m_context . options . elliptic_curves . contains_slow ( curve ) )
2022-02-18 15:59:04 +01:00
return ( i8 ) Error : : NotUnderstood ;
2022-02-17 19:43:42 +01:00
2023-04-14 00:16:18 +02:00
switch ( ( SupportedGroup ) curve ) {
case SupportedGroup : : X25519 :
2022-03-05 18:13:39 +01:00
m_context . server_key_exchange_curve = make < Crypto : : Curves : : X25519 > ( ) ;
break ;
2023-04-14 00:16:18 +02:00
case SupportedGroup : : X448 :
2022-03-05 18:13:39 +01:00
m_context . server_key_exchange_curve = make < Crypto : : Curves : : X448 > ( ) ;
break ;
2023-04-14 00:16:18 +02:00
case SupportedGroup : : SECP256R1 :
2022-03-18 10:39:34 +01:00
m_context . server_key_exchange_curve = make < Crypto : : Curves : : SECP256r1 > ( ) ;
break ;
2023-11-10 16:23:01 +01:00
case SupportedGroup : : SECP384R1 :
m_context . server_key_exchange_curve = make < Crypto : : Curves : : SECP384r1 > ( ) ;
break ;
2022-03-05 18:13:39 +01:00
default :
return ( i8 ) Error : : NotUnderstood ;
}
2022-02-18 17:43:50 +01:00
2022-03-20 21:20:04 +01:00
server_public_key_length = buffer [ 6 ] ;
2022-03-05 18:13:39 +01:00
if ( server_public_key_length ! = m_context . server_key_exchange_curve - > key_size ( ) )
return ( i8 ) Error : : NotUnderstood ;
if ( buffer . size ( ) < 7u + server_public_key_length )
return ( i8 ) Error : : NeedMoreData ;
2022-02-17 19:43:42 +01:00
auto server_public_key = buffer . slice ( 7 , server_public_key_length ) ;
auto server_public_key_copy_result = ByteBuffer : : copy ( server_public_key ) ;
if ( server_public_key_copy_result . is_error ( ) ) {
dbgln ( " ecdhe_rsa_server_key_exchange failed: Not enough memory " ) ;
2022-02-18 15:58:27 +01:00
return ( i8 ) Error : : OutOfMemory ;
2022-02-17 19:43:42 +01:00
}
m_context . server_diffie_hellman_params . p = server_public_key_copy_result . release_value ( ) ;
if constexpr ( TLS_DEBUG ) {
dbgln ( " ECDHE server public key: {:hex-dump} " , server_public_key ) ;
}
2022-03-20 21:20:04 +01:00
return 0 ;
}
ssize_t TLSv12 : : handle_ecdhe_rsa_server_key_exchange ( ReadonlyBytes buffer )
{
u8 server_public_key_length ;
if ( auto result = handle_ecdhe_server_key_exchange ( buffer , server_public_key_length ) ) {
return result ;
}
2022-02-18 10:58:56 +01:00
auto server_key_info = buffer . slice ( 3 , 4 + server_public_key_length ) ;
auto signature = buffer . slice ( 7 + server_public_key_length ) ;
return verify_rsa_server_key_exchange ( server_key_info , signature ) ;
}
ssize_t TLSv12 : : verify_rsa_server_key_exchange ( ReadonlyBytes server_key_info_buffer , ReadonlyBytes signature_buffer )
{
auto signature_hash = signature_buffer [ 0 ] ;
2023-04-14 00:45:32 +02:00
auto signature_algorithm = static_cast < SignatureAlgorithm > ( signature_buffer [ 1 ] ) ;
if ( signature_algorithm ! = SignatureAlgorithm : : RSA ) {
dbgln ( " verify_rsa_server_key_exchange failed: Signature algorithm is not RSA, instead {} " , enum_to_string ( signature_algorithm ) ) ;
2022-02-18 10:58:56 +01:00
return ( i8 ) Error : : NotUnderstood ;
}
auto signature_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( signature_buffer . offset_pointer ( 2 ) ) ) ;
auto signature = signature_buffer . slice ( 4 , signature_length ) ;
if ( m_context . certificates . is_empty ( ) ) {
dbgln ( " verify_rsa_server_key_exchange failed: Attempting to verify signature without certificates " ) ;
return ( i8 ) Error : : NotSafe ;
}
2022-02-22 13:48:52 +01:00
// RFC5246 section 7.4.2: The sender's certificate MUST come first in the list.
2022-02-18 10:58:56 +01:00
auto certificate_public_key = m_context . certificates . first ( ) . public_key ;
Crypto : : PK : : RSAPrivateKey dummy_private_key ;
2023-04-03 19:05:01 +02:00
auto rsa = Crypto : : PK : : RSA ( certificate_public_key . rsa , dummy_private_key ) ;
2022-02-18 10:58:56 +01:00
auto signature_verify_buffer_result = ByteBuffer : : create_uninitialized ( signature_length ) ;
if ( signature_verify_buffer_result . is_error ( ) ) {
dbgln ( " verify_rsa_server_key_exchange failed: Not enough memory " ) ;
return ( i8 ) Error : : OutOfMemory ;
}
auto signature_verify_buffer = signature_verify_buffer_result . release_value ( ) ;
auto signature_verify_bytes = signature_verify_buffer . bytes ( ) ;
rsa . verify ( signature , signature_verify_bytes ) ;
auto message_result = ByteBuffer : : create_uninitialized ( 64 + server_key_info_buffer . size ( ) ) ;
if ( message_result . is_error ( ) ) {
dbgln ( " verify_rsa_server_key_exchange failed: Not enough memory " ) ;
return ( i8 ) Error : : OutOfMemory ;
}
auto message = message_result . release_value ( ) ;
message . overwrite ( 0 , m_context . local_random , 32 ) ;
message . overwrite ( 32 , m_context . remote_random , 32 ) ;
message . overwrite ( 64 , server_key_info_buffer . data ( ) , server_key_info_buffer . size ( ) ) ;
Crypto : : Hash : : HashKind hash_kind ;
switch ( ( HashAlgorithm ) signature_hash ) {
case HashAlgorithm : : SHA1 :
hash_kind = Crypto : : Hash : : HashKind : : SHA1 ;
break ;
case HashAlgorithm : : SHA256 :
hash_kind = Crypto : : Hash : : HashKind : : SHA256 ;
break ;
case HashAlgorithm : : SHA384 :
hash_kind = Crypto : : Hash : : HashKind : : SHA384 ;
break ;
case HashAlgorithm : : SHA512 :
hash_kind = Crypto : : Hash : : HashKind : : SHA512 ;
break ;
default :
dbgln ( " verify_rsa_server_key_exchange failed: Hash algorithm is not SHA1/256/384/512, instead {} " , signature_hash ) ;
return ( i8 ) Error : : NotUnderstood ;
}
auto pkcs1 = Crypto : : PK : : EMSA_PKCS1_V1_5 < Crypto : : Hash : : Manager > ( hash_kind ) ;
auto verification = pkcs1 . verify ( message , signature_verify_bytes , signature_length * 8 ) ;
if ( verification = = Crypto : : VerificationConsistency : : Inconsistent ) {
dbgln ( " verify_rsa_server_key_exchange failed: Verification of signature inconsistent " ) ;
return ( i8 ) Error : : NotSafe ;
}
2022-02-17 19:43:42 +01:00
return 0 ;
}
2022-03-20 21:20:04 +01:00
ssize_t TLSv12 : : handle_ecdhe_ecdsa_server_key_exchange ( ReadonlyBytes buffer )
{
u8 server_public_key_length ;
if ( auto result = handle_ecdhe_server_key_exchange ( buffer , server_public_key_length ) ) {
return result ;
}
auto server_key_info = buffer . slice ( 3 , 4 + server_public_key_length ) ;
auto signature = buffer . slice ( 7 + server_public_key_length ) ;
return verify_ecdsa_server_key_exchange ( server_key_info , signature ) ;
}
ssize_t TLSv12 : : verify_ecdsa_server_key_exchange ( ReadonlyBytes server_key_info_buffer , ReadonlyBytes signature_buffer )
{
auto signature_hash = signature_buffer [ 0 ] ;
auto signature_algorithm = signature_buffer [ 1 ] ;
if ( signature_algorithm ! = ( u8 ) SignatureAlgorithm : : ECDSA ) {
dbgln ( " verify_ecdsa_server_key_exchange failed: Signature algorithm is not ECDSA, instead {} " , signature_algorithm ) ;
return ( i8 ) Error : : NotUnderstood ;
}
auto signature_length = AK : : convert_between_host_and_network_endian ( ByteReader : : load16 ( signature_buffer . offset_pointer ( 2 ) ) ) ;
auto signature = signature_buffer . slice ( 4 , signature_length ) ;
if ( m_context . certificates . is_empty ( ) ) {
dbgln ( " verify_ecdsa_server_key_exchange failed: Attempting to verify signature without certificates " ) ;
return ( i8 ) Error : : NotSafe ;
}
ReadonlyBytes server_point = m_context . certificates . first ( ) . public_key . raw_key ;
auto message_result = ByteBuffer : : create_uninitialized ( 64 + server_key_info_buffer . size ( ) ) ;
if ( message_result . is_error ( ) ) {
dbgln ( " verify_ecdsa_server_key_exchange failed: Not enough memory " ) ;
return ( i8 ) Error : : OutOfMemory ;
}
auto message = message_result . release_value ( ) ;
message . overwrite ( 0 , m_context . local_random , 32 ) ;
message . overwrite ( 32 , m_context . remote_random , 32 ) ;
message . overwrite ( 64 , server_key_info_buffer . data ( ) , server_key_info_buffer . size ( ) ) ;
Crypto : : Hash : : HashKind hash_kind ;
switch ( ( HashAlgorithm ) signature_hash ) {
case HashAlgorithm : : SHA256 :
hash_kind = Crypto : : Hash : : HashKind : : SHA256 ;
break ;
case HashAlgorithm : : SHA384 :
hash_kind = Crypto : : Hash : : HashKind : : SHA384 ;
break ;
case HashAlgorithm : : SHA512 :
hash_kind = Crypto : : Hash : : HashKind : : SHA512 ;
break ;
default :
dbgln ( " verify_ecdsa_server_key_exchange failed: Hash algorithm is not SHA256/384/512, instead {} " , signature_hash ) ;
return ( i8 ) Error : : NotUnderstood ;
}
ErrorOr < bool > res = AK : : Error : : from_errno ( ENOTSUP ) ;
auto & public_key = m_context . certificates . first ( ) . public_key ;
switch ( public_key . algorithm . ec_parameters ) {
case SupportedGroup : : SECP256R1 : {
Crypto : : Hash : : Manager manager ( hash_kind ) ;
manager . update ( message ) ;
auto digest = manager . digest ( ) ;
Crypto : : Curves : : SECP256r1 curve ;
res = curve . verify ( digest . bytes ( ) , server_point , signature ) ;
break ;
}
2023-11-10 16:23:01 +01:00
case SupportedGroup : : SECP384R1 : {
Crypto : : Hash : : Manager manager ( hash_kind ) ;
manager . update ( message ) ;
auto digest = manager . digest ( ) ;
Crypto : : Curves : : SECP384r1 curve ;
res = curve . verify ( digest . bytes ( ) , server_point , signature ) ;
break ;
}
2022-03-20 21:20:04 +01:00
default : {
dbgln ( " verify_ecdsa_server_key_exchange failed: Server certificate public key algorithm is not supported: {} " , to_underlying ( public_key . algorithm . ec_parameters ) ) ;
break ;
}
}
if ( res . is_error ( ) ) {
dbgln ( " verify_ecdsa_server_key_exchange failed: {} " , res . error ( ) ) ;
return ( i8 ) Error : : NotUnderstood ;
}
bool verification_ok = res . release_value ( ) ;
if ( ! verification_ok ) {
dbgln ( " verify_ecdsa_server_key_exchange failed: Verification of signature failed " ) ;
return ( i8 ) Error : : NotSafe ;
}
return 0 ;
}
2021-05-18 21:55:06 +02:00
}