123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352(* Defines all high-level datatypes for the TLS library. It is opaque to clients
of this library, and only used from within the library. *)openCoreopenMirage_cryptotypehmac_key=string(* initialisation vector style, depending on TLS version *)typeiv_mode=|Ivofstring(* traditional CBC (reusing last cipherblock) *)|Random_iv(* TLS 1.1 and higher explicit IV (we use random) *)type'kcbc_cipher=(moduleBlock.CBCwithtypekey='k)type'kcbc_state={cipher:'kcbc_cipher;cipher_secret:'k;iv_mode:iv_mode;hmac:Digestif.hash';hmac_secret:hmac_key}typenonce=stringtype'kaead_cipher=(moduleAEADwithtypekey='k)type'kaead_state={cipher:'kaead_cipher;cipher_secret:'k;nonce:nonce;explicit_nonce:bool;(* RFC 7905: no explicit nonce, instead TLS 1.3 construction is adapted *)}(* state of a symmetric cipher *)typecipher_st=|CBC:'kcbc_state->cipher_st|AEAD:'kaead_state->cipher_st(* context of a TLS connection (both in and out has each one of these) *)typecrypto_context={sequence:int64;(* sequence number *)cipher_st:cipher_st;(* cipher state *)}(* the raw handshake log we need to carry around *)typehs_log=stringlisttypedh_secret=[|`Finite_fieldofMirage_crypto_pk.Dh.secret|`P256ofMirage_crypto_ec.P256.Dh.secret|`P384ofMirage_crypto_ec.P384.Dh.secret|`P521ofMirage_crypto_ec.P521.Dh.secret|`X25519ofMirage_crypto_ec.X25519.secret](* a collection of client and server verify bytes for renegotiation *)typereneg_params=string*stringtypecommon_session_data={server_random:string;(* 32 bytes random from the server hello *)client_random:string;(* 32 bytes random from the client hello *)peer_certificate_chain:X509.Certificate.tlist;peer_certificate:X509.Certificate.toption;trust_anchor:X509.Certificate.toption;received_certificates:X509.Certificate.tlist;own_certificate:X509.Certificate.tlist;own_private_key:X509.Private_key.toption;own_name:[`host]Domain_name.toption;client_auth:bool;master_secret:master_secret;alpn_protocol:stringoption;(* selected alpn protocol after handshake *)}typesession_data={common_session_data:common_session_data;client_version:tls_any_version;(* version in client hello (needed in RSA client key exchange) *)ciphersuite:Ciphersuite.ciphersuite;group:groupoption;renegotiation:reneg_params;(* renegotiation data *)session_id:string;extended_ms:bool;tls_unique:string;}(* state machine of the server *)typeserver_handshake_state=|AwaitClientHello(* initial state *)|AwaitClientHelloRenegotiate|AwaitClientCertificate_RSAofsession_data*hs_log|AwaitClientCertificate_DHEofsession_data*dh_secret*hs_log|AwaitClientKeyExchange_RSAofsession_data*hs_log(* server hello done is sent, and RSA key exchange used, waiting for a client key exchange message *)|AwaitClientKeyExchange_DHEofsession_data*dh_secret*hs_log(* server hello done is sent, and DHE_RSA key exchange used, waiting for client key exchange *)|AwaitClientCertificateVerifyofsession_data*crypto_context*crypto_context*hs_log|AwaitClientChangeCipherSpecofsession_data*crypto_context*crypto_context*hs_log(* client key exchange received, next should be change cipher spec *)|AwaitClientChangeCipherSpecResumeofsession_data*crypto_context*string*hs_log(* resumption: next should be change cipher spec *)|AwaitClientFinishedofsession_data*hs_log(* change cipher spec received, next should be the finished including a hmac over all handshake packets *)|AwaitClientFinishedResumeofsession_data*string*hs_log(* change cipher spec received, next should be the finished including a hmac over all handshake packets *)|Established(* handshake successfully completed *)(* state machine of the client *)typeclient_handshake_state=|ClientInitial(* initial state *)|AwaitServerHelloofclient_hello*(group*dh_secret)list*hs_log(* client hello is sent, handshake_params are half-filled *)|AwaitServerHelloRenegotiateofsession_data*client_hello*hs_log(* client hello is sent, handshake_params are half-filled *)|AwaitCertificate_RSAofsession_data*hs_log(* certificate expected with RSA key exchange *)|AwaitCertificate_DHEofsession_data*hs_log(* certificate expected with DHE key exchange *)|AwaitServerKeyExchange_DHEofsession_data*hs_log(* server key exchange expected with DHE *)|AwaitCertificateRequestOrServerHelloDoneofsession_data*string*string*hs_log(* server hello done expected, client key exchange and premastersecret are ready *)|AwaitServerHelloDoneofsession_data*signature_algorithmlistoption*string*string*hs_log(* server hello done expected, client key exchange and premastersecret are ready *)|AwaitServerChangeCipherSpecofsession_data*crypto_context*string*hs_log(* change cipher spec expected *)|AwaitServerChangeCipherSpecResumeofsession_data*crypto_context*crypto_context*hs_log(* change cipher spec expected *)|AwaitServerFinishedofsession_data*string*hs_log(* finished expected with a hmac over all handshake packets *)|AwaitServerFinishedResumeofsession_data*hs_log(* finished expected with a hmac over all handshake packets *)|Established(* handshake successfully completed *)typekdf={secret:string;cipher:Ciphersuite.ciphersuite13;hash:Digestif.hash';}(* TODO needs log of CH..CF for post-handshake auth *)(* TODO drop master_secret!? *)typesession_data13={common_session_data13:common_session_data;ciphersuite13:Ciphersuite.ciphersuite13;master_secret:kdf;exporter_master_secret:string;resumption_secret:string;state:epoch_state;resumed:bool;client_app_secret:string;server_app_secret:string;}typeclient13_handshake_state=|AwaitServerHello13ofclient_hello*(group*dh_secret)list*string(* this is for CH1 ~> HRR ~> CH2 <~ WAIT SH *)|AwaitServerEncryptedExtensions13ofsession_data13*string*string*string|AwaitServerCertificateRequestOrCertificate13ofsession_data13*string*string*string|AwaitServerCertificate13ofsession_data13*string*string*signature_algorithmlistoption*string|AwaitServerCertificateVerify13ofsession_data13*string*string*signature_algorithmlistoption*string|AwaitServerFinished13ofsession_data13*string*string*signature_algorithmlistoption*string|Established13typeserver13_handshake_state=|AwaitClientHelloHRR13(* if we sent out HRR (also to-be-used for tls13-only) *)|AwaitClientCertificate13ofsession_data13*string*crypto_context*session_ticketoption*string|AwaitClientCertificateVerify13ofsession_data13*string*crypto_context*session_ticketoption*string|AwaitClientFinished13ofstring*crypto_context*session_ticketoption*string|AwaitEndOfEarlyData13ofstring*crypto_context*crypto_context*session_ticketoption*string|Established13typehandshake_machina_state=|Clientofclient_handshake_state|Serverofserver_handshake_state|Client13ofclient13_handshake_state|Server13ofserver13_handshake_state(* state during a handshake, used in the handlers *)typehandshake_state={session:[`TLSofsession_data|`TLS13ofsession_data13]list;protocol_version:tls_version;early_data_left:int32;machina:handshake_machina_state;(* state machine state *)config:Config.config;(* given config *)hs_fragment:string;(* handshake messages can be fragmented, leftover from before *)}(* connection state: initially None, after handshake a crypto context *)typecrypto_state=crypto_contextoption(* record consisting of a content type and a byte vector *)typerecord=Packet.content_type*string(* response returned by a handler *)typerec_resp=[|`Change_encofcrypto_context(* either instruction to change the encryptor to the given one *)|`Change_decofcrypto_context(* either change the decryptor to the given one *)|`Recordofrecord(* or a record which should be sent out *)](* return type of handshake handlers *)typehandshake_return=handshake_state*rec_resplist(* Top level state, encapsulating the entire session. *)typestate={handshake:handshake_state;(* the current handshake state *)decryptor:crypto_state;(* the current decryption state *)encryptor:crypto_state;(* the current encryption state *)fragment:string;(* the leftover fragment from TCP fragmentation *)read_closed:bool;write_closed:bool;}typeerror=[|`AuthenticationFailureofX509.Validation.validation_error|`NoConfiguredCiphersuiteofCiphersuite.ciphersuitelist|`NoConfiguredVersionsoftls_versionlist|`NoConfiguredSignatureAlgorithmofsignature_algorithmlist|`NoMatchingCertificateFoundofstring|`CouldntSelectCertificate]letpp_errorppf=function|`AuthenticationFailurev->Fmt.pfppf"authentication failure: %a"X509.Validation.pp_validation_errorv|`NoConfiguredCiphersuitecs->Fmt.pfppf"no configured ciphersuite: %a"Fmt.(list~sep:(any", ")Ciphersuite.pp_ciphersuite)cs|`NoConfiguredVersionsvs->Fmt.pfppf"no configured version: %a"Fmt.(list~sep:(any", ")pp_tls_version)vs|`NoConfiguredSignatureAlgorithmsas->Fmt.pfppf"no configure signature algorithm: %a"Fmt.(list~sep:(any", ")pp_signature_algorithm)sas|`NoMatchingCertificateFoundhost->Fmt.pfppf"no matching certificate found for %s"host|`CouldntSelectCertificate->Fmt.stringppf"couldn't select certificate"typefatal=[|`Protocol_versionof[|`None_supportedoftls_any_versionlist|`Unknown_recordofint*int|`Bad_recordoftls_any_version]|`Unexpectedof[|`Content_typeofint|`Messageofstring|`Handshakeoftls_handshake]|`Decodeofstring|`Handshakeof[|`Messageofstring|`Fragments|`BadDHofstring|`BadECDHofMirage_crypto_ec.error]|`Bad_certificateofstring|`Missing_extensionofstring|`Bad_mac|`Record_overflowofint|`Unsupported_extension|`Inappropriate_fallback|`No_application_protocol]letpp_protocol_versionppf=function|`None_supportedvs->Fmt.pfppf"none supported, client provided %a"Fmt.(list~sep:(any", ")pp_tls_any_version)vs|`Unknown_record(maj,min)->Fmt.pfppf"unknown record version %u.%u"majmin|`Bad_recordv->Fmt.pfppf"bad record version %a"pp_tls_any_versionvletpp_unexpectedppf=function|`Content_typec->Fmt.pfppf"content type %u"c|`Messagemsg->Fmt.stringppfmsg|`Handshakehs->Fmt.pfppf"handshake %a"pp_handshakehsletpp_handshake_errorppf=function|`Messagemsg->Fmt.stringppfmsg|`Fragments->Fmt.stringppf"fragments are not empty"|`BadDHmsg->Fmt.pfppf"bad DH %s"msg|`BadECDHe->Fmt.pfppf"bad ECDH %a"Mirage_crypto_ec.pp_erroreletpp_fatalppf=function|`Protocol_versione->Fmt.pfppf"version error: %a"pp_protocol_versione|`Unexpectedp->Fmt.pfppf"unexpected: %a"pp_unexpectedp|`Decodemsg->Fmt.pfppf"decode error: %s"msg|`Handshakeh->Fmt.pfppf"handshake error: %a"pp_handshake_errorh|`Bad_certificatemsg->Fmt.pfppf"bad certificate: %s"msg|`Missing_extensionmsg->Fmt.pfppf"missing extension: %s"msg|`Bad_mac->Fmt.stringppf"MAC mismatch"|`Record_overflown->Fmt.pfppf"record overflow %u"n|`Unsupported_extension->Fmt.stringppf"unsupported extension"|`Inappropriate_fallback->Fmt.stringppf"inappropriate fallback"|`No_application_protocol->Fmt.stringppf"no application protocol"typefailure=[|`Erroroferror|`Fataloffatal|`AlertofPacket.alert_type]letpp_failureppf=function|`Errore->pp_errorppfe|`Fatalf->pp_fatalppff|`Alerta->Fmt.pfppf"alert %s"(Packet.alert_type_to_stringa)letcommon_data_to_epochcommonis_serverpeer_name=letown_random,peer_random=ifis_serverthencommon.server_random,common.client_randomelsecommon.client_random,common.server_randominletepoch:epoch_data={side=ifis_serverthen`Serverelse`Client;state=`Established;protocol_version=`TLS_1_0;ciphersuite=`DHE_RSA_WITH_AES_256_CBC_SHA;peer_random;peer_certificate=common.peer_certificate;peer_certificate_chain=common.peer_certificate_chain;peer_name;trust_anchor=common.trust_anchor;own_random;own_certificate=common.own_certificate;own_private_key=common.own_private_key;own_name=common.own_name;received_certificates=common.received_certificates;master_secret=common.master_secret;exporter_master_secret="";alpn_protocol=common.alpn_protocol;session_id="";extended_ms=false;tls_unique=None;}inepochletepoch_of_sessionserverpeer_nameprotocol_version=function|`TLS(session:session_data)->letepoch=common_data_to_epochsession.common_session_dataserverpeer_namein{epochwithprotocol_version=protocol_version;ciphersuite=session.ciphersuite;session_id=session.session_id;extended_ms=session.extended_ms;tls_unique=Somesession.tls_unique;}|`TLS13(session:session_data13)->letepoch:epoch_data=common_data_to_epochsession.common_session_data13serverpeer_namein{epochwithprotocol_version=protocol_version;ciphersuite=(session.ciphersuite13:>Ciphersuite.ciphersuite);extended_ms=true;(* RFC 8446, Appendix D, last paragraph *)state=session.state;exporter_master_secret=session.exporter_master_secret;}letepoch_of_hshs=letserver=matchhs.machinawith|Client_|Client13_->false|Server_|Server13_->trueandpeer_name=Config.(hs.config.peer_name)inmatchhs.sessionwith|[]->None|session::_->Some(epoch_of_sessionserverpeer_namehs.protocol_versionsession)