o
    .j                    @  sL  U d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
mZ d dlmZ d dlmZmZ d dlmZ d dlmZ d dlmZ d d	lmZmZmZmZmZmZmZ d
dlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8 d
dlm9Z: e;dZ<zd dl=Z>W n e?y   zd dl@Z>W n e?y   dZ>Y nw Y nw dZAdZBdZCdZDd)ddZEd*ddZFedZGdd dD ZHd+d,d!d"ZIG d#d$ d$eZJG d%d& d&eKZLG d'd( d(eLZMG d)d* d*eLZNG d+d, d,eLZOG d-d. d.eLZPG d/d0 d0eLZQG d1d2 d2eLZRG d3d4 d4eLZSG d5d6 d6eLZTG d7d8 d8eLZUG d9d: d:eLZVG d;d< d<eLZWG d=d> d>eZXG d?d@ d@eZYG dAdB dBeZZeZj[eYj\eZj]eYj^eZj_eYj^eZj`eYj^eZjaeYj^eZjbeYj^eZjceYjdeZjeeYj\eZjfeYj^eZjgeYjdi
ZhdCeidD< G dEdF dFZjd-dKdLZkd.dOdPZld/dSdTZm	d0d1dYdZZnd2d\d]Zod3d_d`Zpd4dcddZq			d5d6didjZr							d7d8drdsZsG dtdu dueZtG dvdw dweZuG dxdy dyeZvG dzd{ d{eZwG d|d} d}eZxG d~d deZyG dd deZzG dd deZ{ed9ddZ|ed9ddZ}d:ddZ~d;ddZd<ddZd=ddZed>ddZd?ddZd@ddZeeef ZdAddZdBddZd?ddZdCddZeeef ZdDddZdEddZdFddZdGddZeG dd dZeG dd dZdHddZdZd
Zh dZdIddÄZeeef ZeG ddń dŃZeG ddǄ dǃZdJddʄZdKdd̄ZdLddτZeG ddф dуZdMddӄZdNddՄZeG ddׄ d׃ZdOddلZdPdd܄ZeG ddބ dރZdQddZdRddZeeef ZeG dd dZ9eG dd dZdSddZdTddZdUddZeG dd dZdVddZdWddZeG dd dZdXddZdYddZG dd dZG dd dZetjd etjdetjd iZe{jde{jde{jde{jde{jde{jde{jde{jd	e{jd
i	Zdeid< dZddZ			d5d[ddZÐd\ddZed]d!d"ZeG d#d$ d$Zeegdf Zeegee f Zeegdf Zʐd^d%d&ZG d'd( d(ZdS (_      )annotationsN)	unhexlify)contextmanager)	dataclassfield)IntEnum)partial)HMAC)AnyCallable	GeneratorOptionalSequenceTupleTypeVar   )BufferBufferReadErrorCryptoErrorDsaPrivateKeyECDHP256KeyExchangeECDHP384KeyExchangeECDHP521KeyExchangeEcPrivateKeyEd25519PrivateKeyExpiredCertificateErrorHpkeContextInvalidNameCertificateErrorKeyTypePrivateKeyInfoRsaPrivateKeySelfSignedCertificateErrorServerVerifierSignatureErrorUnacceptableCertificateErrorX25519KeyExchangeX25519ML768KeyExchangeclassify_certificates_deridna_encoderebuild_chainverify_with_public_key)Certificatez^[0-9a-fA-F]{8}\.[0-9]$   i  i    returnintc                  C  s&   t dd } | d@ dB }|d> |B S )zGenerate a random GREASE value of the form 0xNaNa (RFC 8701).

    GREASE values are: 0x0A0A, 0x1A1A, 0x2A2A, ..., 0xFAFA (16 possible).
    This matches BoringSSL/Chrome's grease_index_to_value().
    r   r      
      )osurandom)seedlo r7   </home/thesage/.local/lib/python3.10/site-packages/qh3/tls.py_generate_grease_valueI   s   r9   vboolc                 C  s   | d? | d@ ko| d@ dkS )zCheck if a value is a GREASE value (0xNaNa form per RFC 8701).

    A GREASE value has both bytes equal and of the form 0xNa,
    i.e. low nibble is 0x0A: 0x0A0A, 0x1A1A, ..., 0xFAFA.
    r2         r1   r7   )r:   r7   r7   r8   _is_grease_valueT   s   r>   Tc                 C  s   i | ]\}}|t t|d qS N)getattrhashlib).0length	algorithmr7   r7   r8   
<dictcomp>`   s    rF   ))    md5)(   sha1)@   sha256T	remove_tzdatetime.datetimec                 C  s$   t j t jj}| r|jd dS |S )N)tzinfo)datetimenowtimezoneutcreplace)rM   dtr7   r7   r8   utcnowk      rV   c                   @  s|   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdS )AlertDescriptionr   r1         rI   *   +   ,   -   .   /   0   1   2   3   F   G   P   V   Z   m   n   p   q   s   t   x   y   N)__name__
__module____qualname__close_notifyunexpected_messagebad_record_macrecord_overflowhandshake_failurebad_certificateunsupported_certificatecertificate_revokedcertificate_expiredcertificate_unknownillegal_parameter
unknown_caaccess_denieddecode_errordecrypt_errorprotocol_versioninsufficient_securityinternal_errorinappropriate_fallbackuser_canceledmissing_extensionunsupported_extensionunrecognized_namebad_certificate_status_responseunknown_psk_identitycertificate_requiredno_application_protocolech_requiredr7   r7   r7   r8   rX   p   s:    rX   c                   @  s   e Zd ZU ded< dS )AlertrX   descriptionNrr   rs   rt   __annotations__r7   r7   r7   r8   r      s   
 r   c                   @     e Zd ZejZdS )AlertBadCertificateN)rr   rs   rt   rX   rz   r   r7   r7   r7   r8   r          
r   c                   @  r   )AlertCertificateExpiredN)rr   rs   rt   rX   r}   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertDecodeErrorN)rr   rs   rt   rX   r   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertDecryptErrorN)rr   rs   rt   rX   r   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertHandshakeFailureN)rr   rs   rt   rX   ry   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertIllegalParameterN)rr   rs   rt   rX   r   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertInternalErrorN)rr   rs   rt   rX   r   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertProtocolVersionN)rr   rs   rt   rX   r   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertUnexpectedMessageN)rr   rs   rt   rX   rv   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertUnsupportedExtensionN)rr   rs   rt   rX   r   r   r7   r7   r7   r8   r      r   r   c                   @  r   )AlertECHRequiredN)rr   rs   rt   rX   r   r   r7   r7   r7   r8   r      r   r   c                   @     e Zd ZdZdZdS )	Directionr   r   N)rr   rs   rt   DECRYPTENCRYPTr7   r7   r7   r8   r          r   c                   @  s   e Zd ZdZdZdZdZdS )Epochr   r   r,      N)rr   rs   rt   INITIALZERO_RTT	HANDSHAKEONE_RTTr7   r7   r7   r8   r      s
    r   c                   @  s8   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdS )Stater   r   r,   r               r2   	   r1   N)rr   rs   rt   CLIENT_HANDSHAKE_STARTCLIENT_EXPECT_SERVER_HELLO"CLIENT_EXPECT_ENCRYPTED_EXTENSIONS0CLIENT_EXPECT_CERTIFICATE_REQUEST_OR_CERTIFICATE%CLIENT_EXPECT_CERTIFICATE_CERTIFICATE CLIENT_EXPECT_CERTIFICATE_VERIFYCLIENT_EXPECT_FINISHEDCLIENT_POST_HANDSHAKESERVER_EXPECT_CLIENT_HELLOSERVER_EXPECT_FINISHEDSERVER_POST_HANDSHAKEr7   r7   r7   r8   r      s    r   zdict[int, int]_STATE_EXPECTED_EPOCHc                   @  s*   e Zd ZdddZdddZdddZdS )
HKDFExpandrE   r/   rD   infobytes | Nonec                 C  sX   || _ t|d | _d| j }||krtd| d|| _|d u r$d}|| _d| _d S )Nr2   r<   zCannot derive keys larger than z octets.    F)
_algorithmr/   _digest_size
ValueError_length_info_used)selfrE   rD   r   
max_lengthr7   r7   r8   __init__   s   

zHKDFExpand.__init__key_materialbytesr.   c                 C  s   dg}d}| j t|d  | jk rGt|d| j d}||d  || j |t|g ||	  |d7 }| j t|d  | jk sd
|d | j S )Nr   r   sha	digestmod)r   lenr   r	   r   updater   r   appenddigestjoin)r   r   outputcounterhr7   r7   r8   _expand   s   zHKDFExpand._expandc                 C  s   | j rtd| _ | |S )NT)r   r   r   r   r   r7   r7   r8   derive  s   
zHKDFExpand.deriveN)rE   r/   rD   r/   r   r   )r   r   r.   r   )rr   rs   rt   r   r   r   r7   r7   r7   r8   r      s    

r   labelr   
hash_valuerD   c                 C  s2   d|  }t d|t|| t dt| | S )Ns   tls13 z!HBz!B)structpackr   )r   r   rD   
full_labelr7   r7   r8   
hkdf_label  s   r   rE   secretc                 C  s   t | |t|||d|S )N)rE   rD   r   )r   r   r   rE   r   r   r   rD   r7   r7   r8   hkdf_expand_label   s   
r   saltr   c                 C  s$   t |d|  d}|| | S )Nr   r   )r	   r   r   )rE   r   r   r   r7   r7   r8   hkdf_extract.  s   
r   datapasswordr   @EcPrivateKey | DsaPrivateKey | RsaPrivateKey | Ed25519PrivateKeyc                 C  s   t | |}| tjtjtjfv r@d}| tjkrd}n| tjkr'd}n	| tjkr0d}|dus6J t| |d| vS | tjkrMt	| S | tj
krZt| S | tjkrgt| S td)z)
    Load a PEM-encoded private key.
    N     	  s   BEGIN EC PRIVATE KEYzUnsupported private key format)r   get_typer   
ECDSA_P256
ECDSA_P384
ECDSA_P521r   public_bytesDSAr   RSAr    ED25519r   sslSSLError)r   r   	pkey_info
curve_typer7   r7   r8   load_pem_private_key4  s0   

r   list[X509Certificate]c                 C  s   dd t | D S )z8
    Load a chain of PEM-encoded X509 certificates.
    c                 S     g | ]}t |qS r7   )X509Certificate)rC   dr7   r7   r8   
<listcomp>\      z.load_pem_x509_certificates.<locals>.<listcomp>)_load_pem_certs_as_derr   r7   r7   r8   load_pem_x509_certificatesX  s   r  list[bytes]c                 C  s|   d| vrdnd}d| }g }|  |D ](}|r;|d| }|dkr% |S d||d |gd	}|t| q|S )
z
    Decode a PEM bundle into a list of DER byte strings, without instantiating
    the (relatively expensive) ``X509Certificate`` Python wrapper.  Used by
    ``load_store_and_sort`` to feed the bulk classifier.
    s   -----
   
s   
s   -----END CERTIFICATE-----s   -----BEGIN CERTIFICATE-----r   r   Nascii)splitfindr   decoder   r   PEM_cert_to_DER_cert)r   line_endingboundaryoutchunkstart_markerpem_reconstructedr7   r7   r8   r  _  s   r  capathstrc                 C  s4   t j| sdS t | D ]
}t|r dS qdS )zFCheck whether capath exists and contains certs in the expected format.FT)r3   pathisdirlistdir_HASHED_CERT_FILENAME_REmatch)r  namer7   r7   r8   _capath_contains_certst  s   
r  cadatacafile
str | None,tuple[list[bytes], list[bytes], list[bytes]]c              	   C  s
  g }| dur| t|  |dus|durd|r5t|d}| t|  W d   n1 s0w   Y  |rdt|rdt| dD ] }t|d}| t|  W d   n1 s^w   Y  qC| du r|du r|du rt }|  | |j	dd t
|S )a{  
    Given cadata, cafile and capath load X509 certificates and sort
    them into three distinct lists of DER-encoded byte strings:
        - Trust anchors (self-issued CAs with no TLS-purpose EKU)
        - Intermediates (CAs signed by another CA)
        - Others        (self-issued but flagged with TLS-purpose EKU;
                         excluded from trust anchors)
    Nrbz/*T)binary_form)extendr  openreadr  globr   create_default_contextload_default_certsget_ca_certsr'   )r  r  r  raw_dersfpr  default_ctxr7   r7   r8   load_store_and_sort~  s&   r*  certificater   chainserver_nameassert_server_nameocsp_responseNonec                 C  s  |d u rg }t |||d\}}	}
|d u s|du rR|  D ]5}| }||dd |d }|dd d|v rOt|d	krNd
dd |dD }nq|} |d u rZtd|s`td|s|	rt	| 
 |	}t|dkr|dd  D ]	}|t| qwng }zt|}W n ty } ztd|d }~ww z|| 
 dd |D ||pd W d S  ttttfy } zt|tr|du rW Y d }~d S t|jd d }~ww )N)r  r  r  F(r   )z*.zunverified.:   .c                 s  s    | ]	}t t|V  qd S r@   )r  r/   )rC   pr7   r7   r8   	<genexpr>  s    
z%verify_certificate.<locals>.<genexpr>z&unable to determine server name targetz7unable to get local issuer certificate (empty CA store)r,   z(unable to create the verifier x509 storec                 S  s   g | ]}|  qS r7   r   )rC   cr7   r7   r8   r     r   z&verify_certificate.<locals>.<listcomp>r   r   )r*  get_subject_alt_namesr	  r  rT   r   r   r  r   r)   r   r   r   r"   r   verifyr!   r   r   r$   
isinstanceargs)r+  r,  r  r  r  r-  r.  r/  trust_anchorsintermediaries_alt_nameserver_name_candidate	raw_chainistoreeexcr7   r7   r8   verify_certificate  s|   




rH  c                   @  s    e Zd ZdZdZdZdZdZdS )CipherSuitei  i  i  r<   i  N)rr   rs   rt   AES_128_GCM_SHA256AES_256_GCM_SHA384CHACHA20_POLY1305_SHA256EMPTY_RENEGOTIATION_INFO_SCSVGREASEr7   r7   r7   r8   rI    s    rI  c                   @     e Zd ZdZdS )CompressionMethodr   N)rr   rs   rt   NULLr7   r7   r7   r8   rP        rP  c                   @  sT   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdS )ExtensionTyper   r   r1            )   r[   r\   r]   r^   rd   9   iD  i  i   r-   i

  N)rr   rs   rt   SERVER_NAMESTATUS_REQUESTSUPPORTED_GROUPSSIGNATURE_ALGORITHMSALPNCOMPRESS_CERTIFICATEPRE_SHARED_KEY
EARLY_DATASUPPORTED_VERSIONSCOOKIEPSK_KEY_EXCHANGE_MODES	KEY_SHAREQUIC_TRANSPORT_PARAMETERSAPPLICATION_SETTINGSENCRYPTED_SERVER_NAMEECH_OUTER_EXTENSIONSENCRYPTED_CLIENT_HELLOrN  r7   r7   r7   r8   rS    s&    rS  c                   @  s,   e Zd ZdZdZdZdZdZdZdZ	dZ
d	S )
Group         ic  i        i  N)rr   rs   rt   	SECP256R1	SECP384R1	SECP521R1X25519KYBER768DRAFT00X25519ML768X25519X448rN  r7   r7   r7   r8   rj    s    rj  c                   @  s<   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdS )HandshakeTyper   r,   r   r   r2   r4  rT  r=   rY   rl  rm     N)rr   rs   rt   CLIENT_HELLOSERVER_HELLONEW_SESSION_TICKETEND_OF_EARLY_DATAENCRYPTED_EXTENSIONSCERTIFICATECERTIFICATE_REQUESTCERTIFICATE_VERIFYFINISHED
KEY_UPDATECOMPRESSED_CERTIFICATEMESSAGE_HASHr7   r7   r7   r8   rw  (  s    rw  c                   @  rO  )NameTyper   N)rr   rs   rt   	HOST_NAMEr7   r7   r7   r8   r  7  rR  r  c                   @  r   )PskKeyExchangeModer   r   N)rr   rs   rt   PSK_KE
PSK_DHE_KEr7   r7   r7   r8   r  ;  r   r  c                   @  sP   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdS )SignatureAlgorithmi  i  i  i  i  i  i  i  i	  i
  i  i  i  i  i  i  i  N)rr   rs   rt   ECDSA_SECP256R1_SHA256ECDSA_SECP384R1_SHA384ECDSA_SECP521R1_SHA512r   ED448RSA_PKCS1_SHA256RSA_PKCS1_SHA384RSA_PKCS1_SHA512RSA_PSS_PSS_SHA256RSA_PSS_PSS_SHA384RSA_PSS_PSS_SHA512RSA_PSS_RSAE_SHA256RSA_PSS_RSAE_SHA384RSA_PSS_RSAE_SHA512RSA_PKCS1_SHA1SHA1_DSA
ECDSA_SHA1r7   r7   r7   r8   r  @  s$    r  bufr   capacityr   c                 c  s@    t j| |dd}|  | }|V  |  |krtdd S )Nbig	byteorderz!extra bytes at the end of a block)r/   
from_bytes
pull_bytestellr   )r  r  rD   endr7   r7   r8   
pull_blockY  s   r  c                 c  s^    |   | }| | dV  |   }|| }| ||  | |j|dd | | dS )zi
    Context manager to push a variable-length block, with `capacity` bytes
    to write the length.
    Nr  r  )r  seek
push_bytesto_bytes)r  r  startr  rD   r7   r7   r8   
push_blockc  s   
r  funcCallable[[], T]list[T]c                 C  st   g }t | |)}|  | }|  |k r(||  |  |k sW d   |S W d   |S 1 s3w   Y  |S )z
    Pull a list of items.
    N)r  r  r   )r  r  r  itemsrD   r  r7   r7   r8   	pull_listv  s   

r  Callable[[T], None]valuesSequence[T]c                 C  sB   t | | |D ]}|| qW d   dS 1 sw   Y  dS )z
    Push a list of items.
    N)r  )r  r  r  r  valuer7   r7   r8   	push_list  s
   
"r  c                 C  s8   t | |}| |W  d   S 1 sw   Y  dS )z4
    Pull an opaque value prefixed by a length.
    N)r  r  )r  r  rD   r7   r7   r8   pull_opaque  s   $r  r  c                 C  s:   t | | | | W d   dS 1 sw   Y  dS )z2
    Push an opaque value prefix by a length.
    N)r  r  )r  r  r  r7   r7   r8   push_opaque  s   "r  extension_typec                 c  sB    |  | t| d d V  W d    d S 1 sw   Y  d S Nr,   )push_uint16r  )r  r  r7   r7   r8   push_extension  s
   
"r  c                 C  s^   t | d  |  }|tjkrtd| t| ddW  d    S 1 s(w   Y  d S )Nr,   z$ServerName has an unknown name type r  )r  
pull_uint8r  r  r   r  r	  )r  	name_typer7   r7   r8   pull_server_name  s   
$r  c                 C  sN   t | d | tj t| d|d W d    d S 1 s w   Y  d S )Nr,   r  )r  
push_uint8r  r  r  encode)r  r-  r7   r7   r8   push_server_name  s   "r  KeyShareEntryc                 C  s   |   }t| d}||fS r  )pull_uint16r  )r  groupr   r7   r7   r8   pull_key_share  s   
r  c                 C  s"   |  |d  t| d|d  d S )Nr   r,   r   )r  r  )r  r  r7   r7   r8   push_key_share  s   r  c                 C  s   t | ddS Nr   r  )r  r	  r  r7   r7   r8   pull_alpn_protocol     r  protocolc                 C  s   t | d|d d S r  )r  r  )r  r  r7   r7   r8   push_alpn_protocol  s   r  PskIdentityc                 C  s   t | d}|  }||fS r  )r  pull_uint32)r  identityobfuscated_ticket_ager7   r7   r8   pull_psk_identity  s   
r  entryc                 C  s"   t | d|d  | |d  d S )Nr,   r   r   )r  push_uint32r  r  r7   r7   r8   push_psk_identity  s   r  c                 C  s
   t | dS Nr   r  r  r7   r7   r8   pull_psk_binder     
r  binderc                 C  s   t | d| d S r  r  )r  r  r7   r7   r8   push_psk_binder  r  r  c                   @  s"   e Zd ZU dZded< ded< dS )ECHCipherSuitez*HPKE cipher suite: KDF + AEAD identifiers.r/   kdf_idaead_idNrr   rs   rt   __doc__r   r7   r7   r7   r8   r    s   
 r  c                   @  sZ   e Zd ZU dZded< ded< ded< ded< ded	< ded
< ded< ded< ded< dS )	ECHConfiga  
    Parsed ECHConfig structure (RFC 9849 Section 4).

    version: Must be 0xFE0D
    config_id: 1-byte config identifier
    kem_id: HPKE KEM identifier (e.g. 0x0020 for DHKEM(X25519, HKDF-SHA256))
    public_key: KEM public key bytes
    cipher_suites: List of supported HPKE cipher suites
    maximum_name_length: Max length of the SNI name
    public_name: Public-facing server name (used in outer ClientHello)
    extensions: Raw extension bytes
    raw: The raw bytes of this single ECHConfig (version + length + contents)
    r/   version	config_idkem_idr   
public_keyzlist[ECHCipherSuite]cipher_suitesmaximum_name_lengthr  public_name
extensionsrawNr  r7   r7   r7   r8   r    s   
 r  list[ECHConfig]c                 C  s  g }t | d}t|d}| | }| |k r| }| }t|d}| | }|tkr>|| 	 W d   q| }	| }
t|d}g }t|d+}| | }| |k rv| }| }|t	||d | |k s_W d   n1 sw   Y  | }t|d
d}t|d}| |krtd| }| || }|t||	|
||||||d	 W d   n1 sw   Y  | |k sW d   |S W d   |S 1 sw   Y  |S )	a9  
    Parse an ECHConfigList (RFC 9849 Section 4).

    Format:
        ECHConfigList = uint16 length || ECHConfig...
        ECHConfig = uint16 version || uint16 length || contents

    For version 0xFE0D:
        contents = uint8 config_id || uint16 kem_id ||
                   HpkePublicKey(uint16 len || bytes) ||
                   cipher_suites(uint16 len || (uint16 kdf_id, uint16 aead_id)...) ||
                   uint8 maximum_name_length ||
                   opaque public_name(uint16 len || bytes) ||
                   extensions(uint16 len || bytes)
    r  r,   N)r  r  r   r  z/extra bytes at the end of an ECHConfig contents)	r  r  r  r  r  r  r  r  r  )r   r  r  r  ECH_VERSIONr  r  r  r   r  r	  r   r  )r   configsr  list_lengthlist_endconfig_startr  contents_lengthcontents_endr  r  r  r  	cs_lengthcs_endr  r  r  r  r  
config_endr  r7   r7   r8   parse_ech_config_list  sv   



	

6
66r  rG   >   r   r,   r   r  'tuple[ECHConfig, ECHCipherSuite] | Nonec              	   C  s   | D ]X}|j tkr
q|jtkrq|jrBt|jd}d}z| s4| }t|d |d@ r0d}n| r W n	 t	y>   Y qw |rBq|j
D ]}|jtkrY|jtv rY||f    S qEqdS )a  
    Select the first usable ECHConfig from a list.

    Returns (config, cipher_suite) or None if no config is usable.

    Selection criteria (RFC 9849 Section 6.1):
    - Version must be 0xFE0D
    - KEM must be DHKEM(X25519, HKDF-SHA256) (0x0020)
    - At least one cipher suite must use HKDF-SHA256 (0x0001)
      with a supported AEAD
    - No mandatory extensions (we don't support any)
    r  Fr,   i   TN)r  r  r  _ECH_SUPPORTED_KEMr  r   eofr  r  r   r  r  _ECH_SUPPORTED_KDFr  _ECH_SUPPORTED_AEADS)r  configext_bufhas_mandatoryext_typecsr7   r7   r8   select_ech_confige  s8   



r   c                   @     e Zd ZU ded< ded< dS )OfferedPskszlist[PskIdentity]
identitiesr  bindersNr   r7   r7   r7   r8   r       
 r  c                   @  s   e Zd ZU ded< ded< ded< ded< dZded	< d
Zded< dZded< dZded< dZded< dZ	ded< dZ
ded< dZded< dZded< dZded< dZded< d
Zded< eedZded< dZded< dZded < dS )!ClientHellor   randomlegacy_session_id	list[int]r  legacy_compression_methodsNlist[str] | Nonealpn_protocolsFr;   
early_datazlist[KeyShareEntry] | None	key_sharezOfferedPsks | Nonepre_shared_keylist[int] | Nonepsk_key_exchange_modesr  r-  signature_algorithmssupported_groupssupported_versionsalps_protocolscompress_certificate_algorithmscertificate_status_requestdefault_factorylist[Extension]other_extensions
int | Nonegrease_extension1grease_extension2)rr   rs   rt   r   r  r  r  r  r  r-  r  r  r  r  r  r  r   listr  r  r  r7   r7   r7   r8   r    s(   
 r  expected_typec                 C  s(   |   }||krtd| d| dS )a  
    Pull the message type and check it is the expected one.

    The message type is always pulled (even when running under `python -O`)
    so that framing is preserved. If it is not the expected type, we have a
    programming error in the dispatch logic.
    zunexpected handshake type z, expected N)r  r   )r  r   message_typer7   r7   r8   pull_handshake_type  s   r"  c              	     s   t tj td<  tkrtdtdt	dt
djt
djdd d fd
d}t
d| W d    S 1 sJw   Y  S )Nr   zClientHello version is not 1.2rG   r   r,   )r  r  r  r
  Fr.   r0  c                    s   rt d }  }| tjkrtdtt_d S | tjkr.tdj_	d S | tj
kr=tdj_d S | tjkrLtdj_d S | tjkr[tdj_d S | tjkrgt_d S | tjkrxtdtt_d S | tjkrd_d S | tjkrttdtttdttd_d d S | tjkr| d S t | r| d S j!"| |f d S )Nz&PreSharedKey is not the last extensionr,   r   Tr  r  )#r   r  rS  rd  r  r   r  r  ra  r  r\  r  r[  r  rc  r  r  rY  r  r-  r]  r  r  r`  r  r_  r  r  r  r  rZ  r  r>   r  r   r  extension_length	after_pskr  hellor7   r8   pull_extension  sJ   











z)pull_client_hello.<locals>.pull_extensionr.   r0  )r"  rw  ry  r  r  TLS_VERSION_1_2r   r  r  r  r  r  r  r)  r7   r&  r8   pull_client_hello  s"   ,
<<r-  r(  c                 C  s  |  tj t| d | t | |j t| d|j	 t
| d| j|j t
| d| j |j t| d d }d }g }|jD ]\}}|tjkrO||f}qA|tjkrY||f}qA|||f qA|jd ur|t| |j W d    n1 sww   Y  t| tj t
| d| j|j W d    n1 sw   Y  |jd urt| tj t
| dtt| |j W d    n1 sw   Y  t| tj t
| dtt| |j W d    n1 sw   Y  |jd urt| tj t
| d| j|j W d    n	1 sw   Y  |jr2t| tj  |  d | d | d W d    n	1 s-w   Y  |j!d urZt| tj" t
| dtt| |j! W d    n	1 sUw   Y  |d ur~t| |d  | |d  W d    n	1 syw   Y  |j#d urt| tj$ t
| d| j |j# W d    n	1 sw   Y  |j%d urt| tj& t'| |j% W d    n	1 sw   Y  t| tj( t
| d| j|j) W d    n	1 sw   Y  t| tj* t
| d| j|j+ W d    n	1 sw   Y  |d ur+t| |d  | |d  W d    n	1 s&w   Y  |D ] \}}t| | | | W d    n	1 sGw   Y  q-|j,rit| tj- W d    n	1 sdw   Y  |j.d urt| |j. |  d W d    n	1 sw   Y  |j/d urt| tj0  t
| dtt1| |j/j2 t
| dtt3| |j/j4 W d    n	1 sw   Y  W d    n1 sw   Y  W d    d S W d    d S 1 sw   Y  d S )Nr   r   r,   r   )5r  rw  ry  r  r  r+  r  r  r  r  r  r  r
  r  rS  ri  re  r   r  r  r\  r  r  rf  r   r  rd  r  r  r  r^  r  rZ  r  r]  r  rc  r-  rY  r  ra  r  r[  r  r  r`  r  r  r_  r  r  r  r  )r  r(  ech_extensionquic_tp_extensionremaining_extensionsr  extension_valuer7   r7   r8   push_client_hello  s   










 $r2  c                   @  sd   e Zd ZU ded< ded< ded< ded< dZded	< dZd
ed< dZd
ed< eedZ	ded< dS )ServerHellor   r  r  r/   cipher_suitecompression_methodNzKeyShareEntry | Noner  r  r  supported_versionr  list[tuple[int, bytes]]r  )
rr   rs   rt   r   r  r  r6  r   r  r  r7   r7   r7   r8   r3    s   
 r3  c                   s   t  tj t d3   tkrtdt dt	 d   
 dd fdd	}t d
| W d    S 1 sAw   Y  S )Nr   zServerHello version is not 1.2rG   r   )r  r  r4  r5  r.   r0  c                    sr      }    }| tjkr   _d S | tjkr t _d S | tjkr,   _d S j	
|  |f d S r@   )r  rS  ra  r6  rd  r  r  r_  r  r  r   r  r$  r  r(  r7   r8   r)    s   


z)pull_server_hello.<locals>.pull_extensionr,   r*  )r"  rw  rz  r  r  r+  r   r3  r  r  r  r  r,  r7   r8  r8   pull_server_hello  s    
r9  c                 C  s  |  tj t| d | t | |j t| d|j	 | |j
 |  |j t| d |jd urQt| tj | |j W d    n1 sLw   Y  |jd urrt| tj t| |j W d    n1 smw   Y  |jd urt| tj | |j W d    n1 sw   Y  |jD ]\}}t| | | | W d    n1 sw   Y  qW d    n1 sw   Y  W d    d S W d    d S 1 sw   Y  d S Nr   r   r,   )r  rw  rz  r  r  r+  r  r  r  r  r4  r5  r6  r  rS  ra  r  rd  r  r  r_  r  )r  r(  r  r1  r7   r7   r8   push_server_hello  s<   



	"r;  c                   @  s\   e Zd ZU dZded< dZded< dZded< dZded< d	Zd
ed< e	e
dZded< d	S )NewSessionTicketr   r/   ticket_lifetimeticket_age_addr   r   ticket_nonceticketNr  max_early_data_sizer  r7  r  )rr   rs   rt   r=  r   r>  r?  r@  rA  r   r  r  r7   r7   r7   r8   r<    s   
 r<  c                   s   t  t tj t d-   _  _t d_	t d_
d fdd}t d| W d    S 1 s>w   Y  S )	Nr   r   r,   r.   r0  c                    sB      }    }| tjkr  _d S j|  |f d S r@   )r  rS  r`  r  rA  r  r   r  r$  r  new_session_ticketr7   r8   r)    s   
z/pull_new_session_ticket.<locals>.pull_extensionr*  )r<  r"  rw  r{  r  r  r=  r>  r  r?  r@  r  r,  r7   rB  r8   pull_new_session_ticket  s   



rD  rC  c                 C  s0  |  tj t| d | |j | |j t| d|j t| d|j	 t| dK |j
d urMt| tj | |j
 W d    n1 sHw   Y  |jD ]\}}t| | | | W d    n1 siw   Y  qPW d    n1 syw   Y  W d    d S W d    d S 1 sw   Y  d S r:  )r  rw  r{  r  r  r=  r>  r  r?  r@  rA  r  rS  r`  r  r  )r  rC  r  r1  r7   r7   r8   push_new_session_ticket  s*   
"rE  c                   @  sD   e Zd ZU dZded< dZded< dZded< eed	Z	d
ed< dS )EncryptedExtensionsNr  alpn_protocolFr;   r  r   retry_configsr  r7  r  )
rr   rs   rt   rG  r   r  rH  r   r  r  r7   r7   r7   r8   rF    s
   
 rF  c                   s^   t  t tj t d d fdd}t d| W d    S 1 s(w   Y  S )Nr   r.   r0  c                    s~      }    }| tjkrt dtt d _d S | tjkr%d_d S | tj	kr2 
|_d S j|  
|f d S )Nr,   r   T)r  rS  r]  r  r   r  rG  r`  r  ri  r  rH  r  r   r$  r  r  r7   r8   r)     s   




z1pull_encrypted_extensions.<locals>.pull_extensionr,   r*  )rF  r"  rw  r}  r  r  r,  r7   rI  r8   pull_encrypted_extensions  s   
rJ  r  c                 C  s:  |  tj t| d t| dj |jd ur9t| tj t| dt	t
| |jg W d    n1 s4w   Y  |jrRt| tj W d    n1 sMw   Y  |jD ]\}}t| | | | W d    n1 snw   Y  qUW d    n1 s~w   Y  W d    d S W d    d S 1 sw   Y  d S Nr   r,   )r  rw  r}  r  rG  r  rS  r]  r  r   r  r  r`  r  r  )r  r  r  r1  r7   r7   r8   push_encrypted_extensions6  s4   
"rL  c                   @  s,   e Zd ZU dZded< eedZded< dS )r+   r   r   request_contextr  zlist[CertificateEntry]certificatesN)rr   rs   rt   rM  r   r   r  rN  r7   r7   r7   r8   r+   O  s   
 r+   c                   @  s8   e Zd ZU dZded< dZded< eedZded	< dS )
CertificateRequestr   r   rM  Nr  r  r  r7  r  )	rr   rs   rt   rM  r   r  r   r  r  r7   r7   r7   r8   rO  U  s   
 rO  c                 C  sl   t  }t| tj t| d t| d|_d	dd}t| dt|| |_	W d    |S 1 s/w   Y  |S )
Nr   r   r  r   r.   CertificateEntryc                 S  s   t | d}t | d}||fS rK  r  )r  r   r  r7   r7   r8   pull_certificate_entryc  s   

z0pull_certificate.<locals>.pull_certificate_entry)r  r   r.   rP  )
r+   r"  rw  r~  r  r  rM  r  r   rN  )r  r+  rQ  r7   r7   r8   pull_certificate\  s   

rR  c                   sj   t  t tj t d t d_d fdd}t d| W d    S 1 s.w   Y  S )	Nr   r   r.   r0  c                    sH      }    }| tjkrt d j _d S j|  |f d S r  )r  rS  r\  r  r  r  r   r  r$  r  certificate_requestr7   r8   r)  v  s   

z0pull_certificate_request.<locals>.pull_extensionr,   r*  )rO  r"  rw  r  r  r  rM  r  r,  r7   rS  r8   pull_certificate_requesto  s   
rU  c                 C  sj   |  tj t| d  t| d|j dd	d
}t| dt|| |j W d    d S 1 s.w   Y  d S )Nr   r   r  r   r  rP  r.   r0  c                 S  s$   t | d|d  t | d|d  d S )Nr   r   r,   r   r  r  r7   r7   r8   push_certificate_entry  rW   z0push_certificate.<locals>.push_certificate_entry)r  r   r  rP  r.   r0  )	r  rw  r~  r  r  rM  r  r   rN  )r  r+  rV  r7   r7   r8   push_certificate  s   
"rW  c                   @  r  )CertificateVerifyr/   rE   r   	signatureNr   r7   r7   r7   r8   rX    r  rX  c                 C  sT   t | tj t| d |  }t| d}W d    n1 sw   Y  t||dS )Nr   r,   rE   rY  )r"  rw  r  r  r  r  rX  )r  rE   rY  r7   r7   r8   pull_certificate_verify  s   r[  r;  c                 C  sV   |  tj t| d | |j t| d|j W d    d S 1 s$w   Y  d S rK  )r  rw  r  r  r  rE   r  rY  )r  r;  r7   r7   r8   push_certificate_verify  s
   "r\  c                   @  s   e Zd ZU dZded< dS )Finishedr   r   verify_dataN)rr   rs   rt   r^  r   r7   r7   r7   r8   r]    s   
 r]  c                 C  s"   t  }t| tj t| d|_|S Nr   )r]  r"  rw  r  r  r^  r  finishedr7   r7   r8   pull_finished  s   rb  ra  c                 C  s   |  tj t| d|j d S r_  )r  rw  r  r  r^  r`  r7   r7   r8   push_finished  s   rc  c                   @  sJ   e Zd ZdddZddd	ZdddZdddZddddZdddZdS ) KeyScheduler4  rI  c                 C  sZ   t || _t| jd | _|| _d| _td| j | _| j	 
 | _t| j| _d S )Nr2   r   r   )cipher_suite_hashrE   r/   digest_sizer4  
generationrB   newhashcopyr   hash_empty_valuer   r   r   r4  r7   r7   r8   r     s   
zKeySchedule.__init__context_stringr   r.   c                 C  s   d| d | j    S )Ns@                                                                       )ri  rj  r   )r   rm  r7   r7   r8   certificate_verify_data  s   z#KeySchedule.certificate_verify_datar   c                 C  sF   t | j|dd| jd}t|d| j d}|| j   | S )Ns   finishedr   r   r   r   )r   rE   rf  r	   r   ri  rj  r   )r   r   hmac_keyr   r7   r7   r8   finished_verify_data  s   z KeySchedule.finished_verify_datar   c                 C  s"   t | j| j|| j  | jdS )Nr   )r   rE   r   ri  rj  r   rf  )r   r   r7   r7   r8   derive_secret  s   zKeySchedule.derive_secretNr   r   r0  c                 C  sZ   |d u r	t | j}| jrt| j| jd| j| jd| _|  jd7  _t| j| j|d| _d S )Ns   derivedr   r   rE   r   r   )r   rf  rg  r   rE   r   rk  r   r   r7   r7   r8   extract  s   

zKeySchedule.extractr   c                 C  s   | j | d S r@   )ri  r   )r   r   r7   r7   r8   update_hash  r  zKeySchedule.update_hash)r4  rI  )rm  r   r.   r   )r   r   r.   r   )r   r   r.   r   r@   r   r   r.   r0  r   r   r.   r0  )	rr   rs   rt   r   ro  rq  rr  rt  ru  r7   r7   r7   r8   rd    s    

	

	rd  c                   @  s6   e Zd ZdddZddd
dZdddZdddZdS )KeyScheduleProxyr  list[CipherSuite]c                 C  s   t tdd || _d S )Nc                 S  s   | t | fS r@   )rd  )r9  r7   r7   r8   <lambda>  s    z+KeyScheduleProxy.__init__.<locals>.<lambda>)dictmap_KeyScheduleProxy__schedules)r   r  r7   r7   r8   r     s   zKeyScheduleProxy.__init__Nr   r   r.   r0  c                 C     | j  D ]}|| qd S r@   )r}  r  rt  )r   r   kr7   r7   r8   rt       zKeyScheduleProxy.extractr4  rI  rd  c                 C  s
   | j | S r@   )r}  rl  r7   r7   r8   select  r  zKeyScheduleProxy.selectr   r   c                 C  r~  r@   )r}  r  ru  )r   r   r  r7   r7   r8   ru    r  zKeyScheduleProxy.update_hash)r  ry  r@   rv  )r4  rI  r.   rd  rw  )rr   rs   rt   r   rt  r  ru  r7   r7   r7   r8   rx    s
    

rx  r   r   )Nr   )Nr   )N   )Fr   )Fr   )Fr  )Tr   )Tr   )Tr  z1dict[SignatureAlgorithm, tuple[bool | None, int]]r\  r4  c                 C  s   t |  S r@   )CIPHER_SUITES)r4  r7   r7   r8   re    s   re  	supportedofferedlist[Any] | NonerG  Alert | NoneexclT | Noneexcl_fnCallable[[Any], bool] | Nonec                 C  sV   |d ur#| D ]}||v r"|d ur||krq|d ur||rq|  S q|d ur)|d S r@   r7   )r  r  rG  r  r  r9  r7   r7   r8   	negotiate  s   r  signature_algorithmtuple[Any, ...]c                 C  s8   | t jt jfv r
dS tt |  \}}|d u rdS ||fS )Nr7   )r  r   r  r\  )r  is_pss	hash_sizer7   r7   r8   signature_algorithm_params3  s   r  key_scheduleKeySchedule | KeyScheduleProxyc                 c  s*    |  }d V  | |||   d S r@   )r  ru  
data_slice)r  r  
hash_startr7   r7   r8   push_messageB  s   r  c                   @  s   e Zd ZU dZded< ded< ded< ded< d	ed
< ded< d	ed< dZded< eedZded< e	dddZ
e	dddZdS )SessionTicketz6
    A TLS session ticket for session resumption.
    r/   age_addrI  r4  rN   not_valid_afternot_valid_beforer   resumption_secretr  r-  r@  Nr  rA  r  r7  r  r.   r;   c                 C  s   t  }|| jko|| jkS r@   )rV   r  r  )r   rQ   r7   r7   r8   is_valid_  s   zSessionTicket.is_validc                 C  s&   t t | j  d }|| j d S )Ni  l        )r/   rV   r  total_secondsr  )r   ager7   r7   r8   obfuscated_aged  s   zSessionTicket.obfuscated_ager.   r;   r.   r/   )rr   rs   rt   r  r   rA  r   r  r  propertyr  r  r7   r7   r7   r8   r  N  s   
 r  c                  C  s   t  } |  }tdd }d}d}d}t|}tdt| d | d}|d || || || |t| || || || |j	S )a  
    Build a GREASE ECH extension payload for the outer ClientHello.

    RFC 9849 Section 6.2: When ECH is not being offered, the client
    SHOULD include a GREASE ECH extension to make ECH usage indistinguishable.

    Format (ECHClientHello outer):
        type(1) = 0x00
        cipher_suite(4) = kdf_id(2) + aead_id(2)
        config_id(1) = random
        enc_len(2) + enc(32) = valid X25519 KEM output
        payload_len(2) + payload = random (sized to be realistic)
    r   r      r2   r,   r  )
r%   r  r3   r4   r   r   r  r  r  r   )kxencr  r  r  payload_lenpayloadr  r7   r7   r8   _build_grease_ech_extensiono  s"   







r  c                   @  s\  e Zd Z																dydzddZed{d!d"Zed|d$d%Zed}d&d'Zed}d(d)Zed~d*d+Z	ed}d,d-Z
ed~d.d/Z	0ddd8d9Zdd?d@ZddBdCZddHdIZddOdPZddRdSZddTdUZddVdWZddXdYZdd\d]Zdd^d_Zdd`daZddbdcZddddeZddidjZddkdlZddmdnZddsdtZddwdxZdS )ContextNFT	is_clientr;   r  r  r  r   r  r  r  r  list[CipherSuite] | Nonelogger-logging.Logger | logging.LoggerAdapter | Nonemax_early_datar  r-  verify_modehostname_checks_common_nameassert_fingerprintverify_hostnameech_config_listr  r  offer_ec_key_shares offer_certificate_status_requestc              	   C  s  || _ || _|| _|| _|| _|| _|| _d | _g | _d | _	g | _
|| _d | _|	d ur5|	 s5t|	 }	|	| _|
d ur@|
| _n	|rEtjntj| _d | _d | _d | _dd | _t | _t | _| j| jkrl|  jdN  _t | _t | _t | _|d ur|| _n| jt j!t j"t j#g| _t$j%g| _&t'j(g| _)t*j+t*j,t*j-t*j.t*j/t*j0t*j1t*j2t*j3g	| _4|d urt5|| _4|| _6|| _7| jt8j9t8j:t8j;t8j<g| _=| jt>g| _?t@d urtAg| _Bnd | _Bd | _Cd| _Dd | _Ed | _Fd | _Gd | _Hd | _Id | _Jg | _Kd | _Ld| _Md | _Nd| _Od| _Pd| _Qd| _Rd | _Sd | _Td | _U|| _Vd | _Wd | _Xd | _Yd | _Zd | _[|| _\d | _]d | _^d | __d| _`d| _ad | _bd | _cd | _dd | _e|rStfgd| _hd| _itjjk| _ld S d | _hd | _itjjm| _ld S )Nc                 S  s   d S r@   r7   )r   rF  r9  sr7   r7   r8   rz    s    z"Context.__init__.<locals>.<lambda>i  Fr   rG   )n_alpn_protocols_cadata_cafile_capath_hostname_checks_common_name_assert_fingerprint_verify_hostnamer+  certificate_chaincertificate_private_keyhandshake_extensions_max_early_datasession_ticketisasciir(   r	  _server_name_verify_moder   CERT_REQUIRED	CERT_NONEalpn_cbget_session_ticket_cbnew_session_ticket_cbupdate_traffic_key_cbr9   _grease_extension1_grease_extension2_grease_group_grease_cipher_grease_version_cipher_suitesrI  rJ  rK  rL  rP  rQ  _legacy_compression_methodsr  r  _psk_key_exchange_modesr  r  r  r  r  r  r  r  r  r  _signature_algorithmsr  _offer_ec_key_shares!_offer_certificate_status_requestrj  rt  ru  rp  rq  _supported_groupsTLS_VERSION_1_3_supported_versions_brotliCERTIFICATE_COMPRESSION_BROTLI _compress_certificate_algorithmsalpn_negotiatedearly_data_acceptedr  received_extensions_key_schedule_psk_key_schedule_proxy_new_session_ticket_peer_certificate_peer_certificate_chain_ocsp_response_alps_negotiated_peer_alps_settings_local_alps_settings_alps_supported_receive_buffer_session_resumed_enc_key_dec_key_certificate_request_Context__logger_ec_p256_private_key_ec_p384_private_key_ec_p521_private_key_x25519_private_key_x25519_kyber_768_private_key_ech_config_list_ech_config_ech_cipher_suite_ech_hpke_context_ech_offered_ech_accepted_ech_inner_random_ech_retry_configs_ech_inner_ch_hash_ech_inner_ch_bytesr3   r4   client_randomr  r   r   stater   )r   r  r  r  r  r  r  r  r  r-  r  r  r  r  r  r  r  r  r7   r7   r8   r     s   


zContext.__init__r.   X509Certificate | Nonec                 C     | j S r@   )r  r   r7   r7   r8   peer_certificateW     zContext.peer_certificater   c                 C  r  r@   )r  r  r7   r7   r8   peer_certificate_chain[  r  zContext.peer_certificate_chainc                 C  r  )zK
        Returns True if session resumption was successfully used.
        )r  r  r7   r7   r8   session_resumed_     zContext.session_resumedc                 C  r  )zM
        Returns True if ECH was offered and accepted by the server.
        )r  r  r7   r7   r8   ech_acceptedf  r	  zContext.ech_acceptedc                 C  r  )z
        Returns retry_configs from server's EncryptedExtensions if ECH
        was rejected. Can be used to retry with updated configs.
        )r  r  r7   r7   r8   ech_retry_configsm     zContext.ech_retry_configsc                 C  r  )z~
        Whether application_settings (draft-vvv-tls-alps) was negotiated with
        the peer during the handshake.
        )r  r  r7   r7   r8   alps_negotiatedu  r  zContext.alps_negotiatedc                 C  r  )z|
        The application_settings value received from the peer when ALPS was
        negotiated, or None otherwise.
        )r  r  r7   r7   r8   peer_alps_settings}  r  zContext.peer_alps_settingsr   
input_datar   
output_bufdict[Epoch, Buffer]epochr/   r0  c           	      C  s  | j tjkr| |tj  d S |  j|7  _t| jdkrX| jd }dtj	| jdd dd }t| j|k r;d S | jd | }| j|d  | _t
|d}|dkrct| j }|d urc||krct| j tjkrz|tjkrx| ||tj  nt| j tjkr|tjkr| | nt| j tjkr|tjkr| | n|tjkr| | n|tjkr| | nt| j tjkr|tjkr| | nt| j tjkr|tj kr| !||tj"  nht| j tj#kr|tj$kr| %| nUt| j tj&kr|tj'kr| (||tj |tj" |tj)  n4t| j tj*kr=|tj kr+| +||tj)  n|tjkr;| j,r;| -| nt| j tj.krFt|/ sOt0dt| jdksd S d S )Nr   r   r   r  r  r  z-extra bytes at the end of a handshake message)1r  r   r   _client_send_hellor   r   r  r   r/   r  r   r   getr   r   rw  rz  _client_handle_hellor   r}  #_client_handle_encrypted_extensionsr   r~  _client_handle_certificater  %_client_handle_compressed_certificater  "_client_handle_certificate_requestr   r  !_client_handle_certificate_verifyr   r  _client_handle_finishedr   r   r{  !_client_handle_new_session_ticketr   ry  _server_handle_hellor   r   _server_handle_finishedr  *_server_handle_client_encrypted_extensionsr   r  r   )	r   r  r  r  r!  message_lengthmessage	input_bufexpected_epochr7   r7   r8   handle_message  s   










zContext.handle_messagerC  r<  r  r  r  c                 C  sb   | j d}t| j j|d|j| j jd}t }t|j| j j	|j
|tj|jd |||| j|jd	S )Ns
   res masters
   resumptionr   )seconds)	r  r4  rA  r  r  r  r  r-  r@  )r  rr  r   rE   r?  rf  rV   r  r>  r4  rA  rP   	timedeltar=  r  r@  )r   rC  r  resumption_master_secretr  	timestampr7   r7   r8   _build_session_ticket  s,   zContext._build_session_ticketr   c                 C  s  g }g }| j D ]}|tjkr'| jr t | _|tj| j f |tj q|tjkrE| jr>t	 | _
|tj| j
 f |tj q|tjkrc| jr\t | _|tj| j f |tj q|tjkr~t | _|tj| j f |tj q|tjkrt | _|tj| j f |tj | jd ur| jd qt|r||df || qt|sJ dd}| jd urz>t| j}t|}|d ur|\| _| _d}| jd ur| jd| jj| jj| jj| jj | jj! n| jd ur| jd W n t"y   | jd ur| jd Y nw t#| j$}|r9d| _%| j&||d	}	|t'j(|	f | jj!}
nt) }	|t'j(|	f | j*}
| jd urS| jd
 t+d&i d| j,d| j-ddd | j.D d| j/d| j0d|d| j1d|
d| j2d|d| j3d| j0d| j4d| j5d|d| j6d| j7}| j8r&| j8j9r&t:| j8j;| _<| j<=| j8j> | j<?d}| j<j@}| j8jAd urd|_BtC| j8jD| j8jEfgtF|gd|_GtHd d!}tI|| |J | d" }| j<K|Ld#| | j<M|}||jGjNd#< | j<K|L||d" |  |jBr&| j<?d$}| OtPjQtRjS| j<j;| tTd%d | j.D | _U| jU=d  tV| jU| tI|| W d    n	1 sNw   Y  | WtXjY d S )'NzJTLS: Advertising to peer post-quantum algorithm using X25519ML768 (0x11EC)rn  zno key share entriesFTzOECH: Selected config_id=%d, KEM=0x%04X, KDF=0x%04X, AEAD=0x%04X, public_name=%sz3ECH: No usable config found, falling back to GREASEz:ECH: Failed to parse ECHConfigList, falling back to GREASE)r  r  z*ECH: GREASE extension added to ClientHellor  r  r  c                 S  r   r7   r/   rC   xr7   r7   r8   r   m  r   z.Context._client_send_hello.<locals>.<listcomp>r
  r  r  r  r-  r  r  r  r  r  r  r  r  r  
   res binderr#  i   r  r   r      c e trafficc                 S  s   g | ]}t |s|qS r7   )r>   )rC   r  r7   r7   r8   r     s    r7   )Zr  rj  rp  r  r   r  r   r  rq  r   r  rr  r   r  ru  r%   r  rt  r&   r  r  debugr>   r   r  r  r   r  r  r  r  r  r  r  	Exceptionr  r  r  _build_ech_extensionrS  ri  r  r  r  r   r  r  r  r  r  r  r  r  r  r  r  r  r  rd  r4  r  rt  r  rr  rf  rA  r  r  r@  r  r   r  r   r2  r  ru  r  rq  r  r  r   r   r   r   rx  r  r  
_set_stater   r   )r   r  r  r  r  ech_config_selectedr  resultr  ech_extension_dataouter_server_namer(  
binder_keybinder_lengthtmp_bufhash_offsetr  	early_keyr7   r7   r8   r    sL  












	


zContext._client_send_hellor  list[KeyShareEntry]r  r	  c                   s	  j dusJ jdusJ td_dj j }tj jjjjj	j j
|d_j  g }|j |tj jdurJ|tj |tj jdur[|tj jdurf|tj |tj |tj |tj jD ]\}}|tjkr|| q{jD ]\}}|tjkr|| q|j tdt|d  d}t|d |D ]}| | qW d   n1 sw   Y  tdd}| t! |"j t#|dd	 t$|d|j d
d j%D  t$|d|j&j' t|d j(durAt)|tj*- t|d |&d t#|dj(+d W d   n	1 s,w   Y  W d   n	1 s<w   Y  t)|tj, |&d W d   n	1 sXw   Y  t)|tj- |"|j. W d   n	1 suw   Y  W d   n	1 sw   Y  |j.}	j(rtj(+dnd}
t/dj j0|
 }t|	| }|d }|dkr|d| 7 }|dkr|	d| 7 }	d}t|	| }d, fdd}|d| }t1j}|tj,|f t2d-i dj3dj4ddd j%D dj'djd|dj5dj j6dj7d|d j8d!jd"jd#|d$jd%j}td&d}t9|| |j.d'd }jj:||	d(}||}td&d}|&t;j< t|d)C | t! |"j t#|dj4 t$|d|j d*d j%D  t$|d|j&j' t|d j(durt)|tj*- t|d |&d t#|dj(+d W d   n	1 sw   Y  W d   n	1 sw   Y  t)|tj, |&d W d   n	1 sw   Y  t)|j W d   n	1 sw   Y  t)|tj t$|d|j j7 W d   n	1 sw   Y  jdurKt)|tj t$|dt=t>|j W d   n	1 sFw   Y  t)|tj t$|dt=t?|| W d   n	1 sgw   Y  jdurt)|tj t$|d|j j W d   n	1 sw   Y  jdurt)|tj t$|dt=t>|j W d   n	1 sw   Y  t)|tj t$|d|j&j5 W d   n	1 sw   Y  t)|tj t$|d|j j8 W d   n	1 sw   Y  t)|tj t$|d|j | W d   n	1 sw   Y  jD ]&\}}|tjkrAt)|| |"| W d   n	1 s<w   Y  qjD ]&\}}|tjkrkt)|| |"| W d   n	1 sfw   Y  qFt)|j |&d W d   n	1 sw   Y  W d   n	1 sw   Y  W d   n	1 sw   Y  |j._@jAdurňjABd+j jCt t|t|	 |S ).a  
        Build a real ECH extension for the outer ClientHello.

        This constructs the inner ClientHello (EncodedClientHelloInner),
        encrypts it with HPKE, and returns the outer ECH extension payload.

        The inner CH contains the real SNI (server_name), while the outer
        CH will have its SNI replaced with the ECH config's public_name.

        RFC 9849 Section 5.1:
        EncodedClientHelloInner = inner CH without Handshake header,
          with legacy_session_id = empty, padded to hide true SNI length.

        The AAD is the complete outer ClientHello (serialized with Handshake
        header) with the ECH payload field replaced by zeros.
        NrG   s   tls ech )r  r  r  r  r   r   r,   r  i   r   c                 S  r   r7   r*  r+  r7   r7   r8   r   	  r   z0Context._build_ech_extension.<locals>.<listcomp>r   r  rn  rU  r  r   r.   c                   s   t dt  d t|  d}|d |jj |jj |jj |t  |	  |t|  |	|  |j
S )z1Build ECH extension structure with given payload.r2   r,   r  r   )r   r   r  r  r  r  r  r  r  r  r   )r  r  r  r   r7   r8   _build_ech_header*	  s   


z7Context._build_ech_extension.<locals>._build_ech_headerr  r  r  c                 S  r   r7   r*  r+  r7   r7   r8   r   A	  r   r
  r  r  r  r-  r  r  r  r  r  r  r  r  i    r   )aad	plaintextr   c                 S  r   r7   r*  r+  r7   r7   r8   r   	  r   z_ECH: Built real ECH extension (config_id=%d, enc=%d bytes, payload=%d bytes, inner_ch=%d bytes))r  r   r.   r   r7   )Dr  r  r3   r4   r  r  r   r  r  r  r  r  r  r   r  rS  r\  r  rf  rd  r  r^  r]  rc  ra  r[  r  re  r  r   r   r  r  r+  r  r  r  r  r  r  r  r  rY  r  ri  rh  r   maxr  r  r  r   r  r  r  r  r  r2  sealrw  ry  r   r  r  r  r  r/  r  )r   r  r  r   compressed_typesr  r@  outer_ext_buf	inner_bufencoded_innerserver_name_lenpadding_needed	total_len	remainderaead_tag_lenr  r>  ech_placeholderaad_extensions	aad_helloaad_bufr?  
ciphertextr4  inner_ch_buf	ext_valuer7   r=  r8   r1    s  













	










 
	zContext._build_ech_extension
peer_hellor3  r4  rI  raw_server_helloc                 C  s   | j dusJ | jdusJ |jdd }t|}d|dd< t|}td| }|| j |t| |	 }t
|d }	t|t|	| j d	}
t||
d
|dd}| jdurc| jd||k ||kS )ax  
        Check ECH acceptance confirmation per RFC 9849 Section 7.2.

        The server signals ECH acceptance by embedding a confirmation value
        in the last 8 bytes of ServerHello.random. To verify:
        1. Zero the last 8 bytes of ServerHello.random in the raw wire bytes
        2. Compute transcript hash over inner_CH + modified_ServerHello
        3. Compute accept_confirmation = HKDF-Expand-Label(
               HKDF-Extract(0, inner_random),
               "ech accept confirmation",
               transcript_hash, 8)
        4. Compare with original last 8 bytes of ServerHello.random

        IMPORTANT: We must use the original wire bytes (raw_server_hello) and
        modify them directly, rather than re-serializing with push_server_hello(),
        because push_server_hello() may reorder extensions differently from the
        original wire format.
        Nrl  rG   s           ro  &   r   r2   rs  s   ech accept confirmationr   zECH acceptance check: match=%s)r  r  r  	bytearrayre  rB   rh  r   r   r   r/   r   r   r  r/  )r   rS  r4  rT  	candidatemodified_shrE   transcript_hashtranscript_ech_confrf  prkaccept_confirmationr7   r7   r8   _check_ech_acceptance
  s:   	
zContext._check_ech_acceptancer"  c                 C  sT  t |}|j}t| j|jgtdtd}|j| jvrt	d|j
| jvr(t	d| jrI| jd urI| |||| _| jd urI| jd| jrFdnd |jd urh| jd u s^|jdks^|| jjkr`t	| j| _d	| _n| j|| _d | _d | _|jd
 }d }|jd tjkr| jd ur| j|}nU|jd tjkr| j|}| jd ur| jd n;|jd tjkr| j d ur| j |}n'|jd tj!kr| j"d ur| j"|}n|jd tj#kr| j$d ur| j$|}|d u rt	d| jr| j%d usJ t&'d| jj( | j_)| jj)*| j% | j+|j | j,| | -t.j/t0j1d | 2t3j4 d S )NzUnsupported cipher suiter  z9ServerHello has a compression method we did not advertisez.ServerHello has a version we did not advertisezECH: Server %s ECHacceptedrejectedr   Tr   zBTLS: Post-quantum safety achieved using X25519ML768 (key-exchange)z7ServerHello selected a key share group we did not offerr      s hs traffic)5r9  r   r  r  r4  r   r>   r5  r  r   r6  r  r  r  r]  r  r  r/  r  r  r  r  r  r  r  rj  ru  r  exchangert  r  rp  r  rq  r  rr  r  r  rB   rh  rE   ri  r   ru  rt  _setup_traffic_protectionr   r   r   r   r2  r   r   )r   r"  r  rS  rT  r4  peer_public_key
shared_keyr7   r7   r8   r  [
  s   










zContext._client_handle_helloc                 C  s   t |}|j| _|j| _|j| _| jr| | j |jD ]\}}|tj	kr-d| _
|| _ nq|jd urN| jr8t| jrN|j| _| jd urN| jdt|j | tjtjd | j|j | jri| tj d S | tj  d S )NTz<ECH: Server rejected ECH, provided %d bytes of retry_configs   c hs traffic)!rJ  rG  r  r  r  r  r  r  rS  rf  r  r  rH  r  r   r  r  r  r/  r   rc  r   r   r   r   r  ru  r   r  r2  r   r   r   r   r"  encrypted_extensionsr  rR  r7   r7   r8   r  
  s:   



z+Context._client_handle_encrypted_extensionsc                 C  s,   |  t| | j|j | tj d S r@   )_process_certificaterR  r  ru  r   r2  r   r   r   r"  r7   r7   r8   r  
  s   z"Context._client_handle_certificatec                 C  s   t |tj t|d | }| }t|d}W d    n1 s#w   Y  |tks0td u r4t	dzt
|}W n tyF   t	dw t||krQt	dttjgt|dd | }| tt|d | j|j | tj d S )Nr   z-unsupported certificate compression algorithmz certificate decompression failedz(certificate decompressed length mismatchr  r  )r"  rw  r  r  r  pull_uint24r  r  r  r   
decompressr0  r   r   r~  r  ri  rR  r   r  ru  r   r2  r   r   )r   r"  rE   uncompressed_length
compressedcertificate_bodycertificate_messager7   r7   r8   r  
  s0   
z-Context._client_handle_compressed_certificater+  r+   c                   s   t  jd d d}z3| s<| }| }|tjkr7| }|dkr/| }||| _	n||d  nn| rW n	 t
yF   Y nw t jd d | _ fddtdt jD | _d S )Nr   r   r  c                   s   g | ]}t  j| d  qS )r   )r   rN  )rC   rD  r+  r7   r8   r   2  s    z0Context._process_certificate.<locals>.<listcomp>)r   rN  r  r  rS  rZ  r  rk  r  r  r   r   r  ranger   r  )r   r+  r  r  ext_lenstatus_typeresp_lenr7   rq  r8   ri    s,   

zContext._process_certificatec                 C  s(   t || _| j|j | tj d S r@   )rU  r  r  ru  r   r2  r   r   rj  r7   r7   r8   r  7  s   
z*Context._client_handle_certificate_requestc           
   
   C  s`  t |}|j| jvrtdzt| j |j| jd|j	 W n t
y2 } ztt|d }~ww | jtjkr_| jrI| jsI| jd urI| jj}n| j}t| j| j| j| j| j|| j| jd | jd ur| jdd }t|}t |}|st!d| t"|# }|| j$ % }	|	|krt!d|&  d|	&  d	| j'|j( | )t*j+ d S )
Nz@CertificateVerify has a signature algorithm we did not advertise!   TLS 1.3, server CertificateVerify)r  r  r  r+  r,  r-  r.  r/  r3   zFingerprint of invalid length: z&Fingerprints did not match. Expected "z", got ""),r[  rE   r  r   r*   r  r  r  ro  rY  r#   r  r  r   r  r  r  r  r  r  rH  r  r  r  r  r  r  r  rT   lowerr   HASHFUNC_MAPr  r   r   r  r   r   hexru  r   r2  r   r   )
r   r"  r;  rF  cert_server_namefingerprintdigest_lengthhashfuncexpect_fingerprintpeer_fingerprintr7   r7   r8   r  <  sp   



z)Context._client_handle_certificate_verifyc           	      C  s  t |}| j| j}|j|krt| j|j | jjdks!J | j	d  | 
tjtjd | jd}| jr\t| j| t|ttj| jfgd W d    n1 sWw   Y  | jd urt| j| t|t| jjdd | jg| j D d W d    n1 sw   Y  d | j| jfvrg }t| jtrt j!t j"g}n1t| jt#r| jj$dkrt j%g}n | jj$d	krt j&g}n| jj$d
krt j'g}n
t| jt(rt j)g}t*|| jj+t,d}| jj-| j.dgt/|R  }t| j| t0|t1||d W d    n	1 sw   Y  t| j| t2|t3| j| j4d W d    n	1 s/w   Y  || _4| 5tj6tj| jj7| j4 | 8t9j: | j;rb| j<sd| j=d ur^| j=>d t?dd S d S )Nr,      s ap traffic   c ap traffic)r  c                 S  s    g | ]}|d ur|  dfqS )Nr   r8  )rC   certr7   r7   r8   r     s
    
z3Context._client_handle_finished.<locals>.<listcomp>rM  rN  r   r   r    No supported signature algorithms!   TLS 1.3, client CertificateVerifyrZ  r^  zLECH: Handshake completed for outer (public_name), raising ech_required alertz*ECH was offered but rejected by the server)@rb  r  rq  r  r^  r   ru  r   rg  rt  rc  r   r   r   r   rr  r  r  rL  rF  rS  rf  r  r  rW  r+   rM  r+  r  r  r<  r    r  r  r  r   r   r  r  r  r   r   r  r  r   signro  r  r\  rX  rc  r]  r  r  r   r4  r2  r   r   r  r  r  r/  r   )	r   r"  r  ra  expected_verify_datanext_enc_keyr  r  rY  r7   r7   r8   r    s   

		zContext._client_handle_finishedc                 C  s2   t |}| jd ur| || j}| | d S d S r@   )rD  r  r)  r  )r   r"  rC  r@  r7   r7   r8   r    s   
z)Context._client_handle_new_session_ticketinitial_bufhandshake_buf
onertt_bufc               	   C  s$  t |}g }t| jtrtjtjg}n1t| jtr:| jjdkr$tj	g}n | jjdkr/tj
g}n| jjdkr9tjg}n
t| jtrDtjg}t| j|jtdtd}t| j|jtd}t| j|j}	t||jtd}
t| j|jtd}| jd urt| j|jtd	| _|j| _t !d
| _"|j#| _#|j$| _%| j&r| &| j | j'r|j$D ]\}}|t(j)krd| _*| j+,t(j)| j-f  nqd }| j.d urn|	d urn|j/d urnt0|j/j1dkrnt0|j/j2dkrn|j/j1d }| .|d }|d urn|j3rn|j4|krnt5|| _6| j67|j8 | j69d}| j6j:}|; | d }|<|d |d | }| j6=|<d| | j6>|}||krBtd| j6=|<||d |  d| _?|j@rl| j69d}d| _A| BtCjDtEjF| j6j4| d}|d u rt5|| _6| j67d  | j6=|jG d }d }d }|jHD ]}|d }|d tIjJkrtK | _L| jLM }| jLN|}tIjJ} nr|d tIjOkrtP | _Q| jQN|}| jQR }tIjO} nV|d tIjSkrtT | _U| jUM }| jUN|}tIjS} n:|d tIjVkrtW | _X| jXM }| jXN|}tIjV} n|d tIjYkr tZ | _[| j[M }| j[N|}tIjY} nq|d u r+tdt\| j"| j#||||f||d}t]| j6| t^|| W d    n	1 sQw   Y  | j67| | _tCj`tEjad | _tCjDtEjad t]| j6| tb|tc| j| jA| j+d W d    n	1 sw   Y  |d u rt]| j6| td|teddd | jfg| jg D d W d    n	1 sw   Y  | jjh| j6idgtj|
R  }t]| j6| tk|tl|
|d W d    n	1 sw   Y  t]| j6| tm|tn| j6>| jod W d    n	1 sw   Y  | j6jpdksJ | j67d  | _tCj`tEjqd | j69d | _r| j*sU| j6>| js| _ttud!d"}tm|tn| jtd | j6=|jG | jvd ur|	d urtwd#txyd$t !d%d dt !d!| jzd&| _{t||| j{ | }| j{| j+}| v| | ~tj d S )'Nr   r   r   zNo supported cipher suiter^  zNo supported compression methodr  zNo supported protocol versionzNo common ALPN protocolsrG   Tr   r   r-  r   zPSK validation failedr.  z+No supported key share group in ClientHello)r  r  r4  r5  r  r  r6  ra  rf  )rG  r  r  r   c                 S  s   g | ]}|  d fqS )r   r8  r+  r7   r7   r8   r     s    
z0Context._server_handle_hello.<locals>.<listcomp>r  rv  rZ  r  r,   r  r  rK   r  iQ Ir   )r=  r>  r?  r@  rA  )r-  r<  r  r    r  r  r  r   r   r  r  r  r   r   r  r  r  r   r>   r  r
  r  r  r  r  r  r   r  r  r  r  r   r3   r4   server_randomr  r  r  r  r  rS  rf  r  r  r   r  r  r  r   r  r  r  r4  rd  r  rt  r  rr  rf  r  r  ru  rq  r  r  r  r  r   r   r   r   r   r  rj  ru  r%   r  r  rb  rt  r&   r  shared_ciphertextrp  r   r  rq  r   r  rr  r   r  r3  r  r;  rc  r   r   rL  rF  rW  r+   r+  r  r  ro  r  r\  rX  rc  r]  r  rg  r   _next_dec_keyr  _expected_verify_datar   r  r<  r   unpackr  r  rE  r)  r2  r   r   ) r   r"  r  r  r  rS  r  r4  r5  psk_key_exchange_moder  r6  r  r@  r  r  r  r7  r8  r:  r  expected_binderr;  r  group_kxre  r  rd  r(  rY  r  r@  r7   r7   r8   r    s  
















	



		
	
	
zContext._server_handle_helloc                 C  s>   t |}|jD ]\}}|tjkr|| _ nq| j|j d S r@   )rJ  r  rS  rf  r  r  ru  r   rg  r7   r7   r8   r  >  s   
z2Context._server_handle_client_encrypted_extensionsc                 C  sz   t |}| jr| j| j| _|j| jkrt| jr!| j|j	 | j
| _d | _
| tjtj| jj| j | tj d S r@   )rb  r  r  rq  r  r  r^  r   ru  r   r  r  r   r   r   r   r4  r2  r   r   )r   r"  r  ra  r7   r7   r8   r  I  s$   zContext._server_handle_finished	directionr   r   r   c                 C  s<   | j |}|tjkr|| _n|| _| ||| j j| d S r@   )r  rr  r   r   r  r  r  r4  )r   r  r  r   keyr7   r7   r8   rc  g  s   
z!Context._setup_traffic_protectionr  r   c                 C  s&   | j r| j d| jj|j || _d S )NzTLS %s -> %s)r  r/  r  r  )r   r  r7   r7   r8   r2  u  s   
zContext._set_state)NNNNNNNNNFNTNNFF)"r  r;   r  r  r  r   r  r  r  r  r  r  r  r  r  r  r-  r  r  r  r  r;   r  r  r  r;   r  r   r  r  r  r;   r  r;   )r.   r  )r.   r   r  )r.   r   )r   )r  r   r  r  r  r/   r.   r0  )rC  r<  r  r  r.   r  )r  r   r.   r0  )r  r<  r  r	  r.   r   )rS  r3  r4  rI  rT  r   r.   r;   )r"  r   r  r   r.   r0  )r"  r   r.   r0  )r+  r+   r.   r0  )
r"  r   r  r   r  r   r  r   r.   r0  )r  r   r  r   r   r   r.   r0  )r  r   r.   r0  )rr   rs   rt   r   r  r  r  r  r
  r  r  r  r$  r)  r  r1  r]  r  r  r  r  ri  r  r  r  r  r  r  r  rc  r2  r7   r7   r7   r8   r    sv     <
b
 
0  
c
J
i
-

"


E 


  
5

r  r  )r:   r/   r.   r;   )T)rM   r;   r.   rN   )r   r   r   r   rD   r/   r.   r   )rE   r/   r   r   r   r   r   r   rD   r/   r.   r   )rE   r/   r   r   r   r   r.   r   r@   )r   r   r   r   r.   r   )r   r   r.   r   )r   r   r.   r  )r  r  r.   r;   )NNN)r  r   r  r  r  r  r.   r  )NNNNNTN)r+  r   r,  r   r  r   r  r  r  r  r-  r  r.  r;   r/  r   r.   r0  )r  r   r  r/   r.   r   )r  r   r  r/   r  r  r.   r  )
r  r   r  r/   r  r  r  r  r.   r0  )r  r   r  r/   r.   r   )r  r   r  r/   r  r   r.   r0  )r  r   r  r/   r.   r   )r  r   r.   r  )r  r   r-  r  r.   r0  )r  r   r.   r  )r  r   r  r  r.   r0  )r  r   r  r  r.   r0  )r  r   r.   r  )r  r   r  r  r.   r0  )r  r   r.   r   )r  r   r  r   r.   r0  )r   r   r.   r  )r  r  r.   r  )r  r   r   rw  r.   r0  )r  r   r.   r  )r  r   r(  r  r.   r0  )r  r   r.   r3  )r  r   r(  r3  r.   r0  )r  r   r.   r<  )r  r   rC  r<  r.   r0  )r  r   r.   rF  )r  r   r  rF  r.   r0  )r  r   r.   r+   )r  r   r.   rO  )r  r   r+  r+   r.   r0  )r  r   r.   rX  )r  r   r;  rX  r.   r0  )r  r   r.   r]  )r  r   ra  r]  r.   r0  )r4  rI  r.   r/   )r  r  r  r  rG  r  r  r  r  r  r.   r?   )r  r/   r.   r  )r  r  r  r   r.   r   )r.   r   )
__future__r   rP   r#  rB   loggingr3   rer   r   binasciir   
contextlibr   dataclassesr   r   enumr   	functoolsr   hmacr	   typingr
   r   r   r   r   r   r   _hazmatr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r   compiler  brotlir  ImportError
brotlicffir  r+  r  r  r9   r>   r?   rz  rV   rX   r0  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r*  rH  rI  rP  rS  rj  rw  r  r  r  r  r  r  r  r  r  r  r  r  r/   r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   	Extensionr  r  r"  r-  r2  r3  r9  r;  r<  rD  rE  rF  rJ  rL  rP  rO  rR  rU  rW  rX  r[  r\  r]  rb  rc  rd  rx  rJ  rK  rL  r  r  r  r  r  r  r  r  r  r  r\  re  r  r  r  r  r  AlpnHandlerSessionTicketFetcherSessionTicketHandlerr  r  r7   r7   r7   r8   <module>   s   $l
	-
$%[		M1 A~!		9,