123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442(* 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=Cstruct.t(* initialisation vector style, depending on TLS version *)typeiv_mode=|IvofCstruct.t(* traditional CBC (reusing last cipherblock) *)|Random_iv(* TLS 1.1 and higher explicit IV (we use random) *)type'kcbc_cipher=(moduleCipher_block.S.CBCwithtypekey='k)type'kcbc_state={cipher:'kcbc_cipher;cipher_secret:'k;iv_mode:iv_mode;hmac:Hash.hash;hmac_secret:hmac_key}typenonce=Cstruct.ttype'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=Cstruct.tlisttypedh_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=Cstruct.t*Cstruct.ttypecommon_session_data={server_random:Cstruct.t;(* 32 bytes random from the server hello *)client_random:Cstruct.t;(* 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:Cstruct.t;extended_ms:bool;tls_unique:Cstruct.t;}(* 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*Cstruct.t*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*Cstruct.t*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*Cstruct.t*Cstruct.t*hs_log(* server hello done expected, client key exchange and premastersecret are ready *)|AwaitServerHelloDoneofsession_data*signature_algorithmlistoption*Cstruct.t*Cstruct.t*hs_log(* server hello done expected, client key exchange and premastersecret are ready *)|AwaitServerChangeCipherSpecofsession_data*crypto_context*Cstruct.t*hs_log(* change cipher spec expected *)|AwaitServerChangeCipherSpecResumeofsession_data*crypto_context*crypto_context*hs_log(* change cipher spec expected *)|AwaitServerFinishedofsession_data*Cstruct.t*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:Cstruct.t;cipher:Ciphersuite.ciphersuite13;hash:Mirage_crypto.Hash.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:Cstruct.t;resumption_secret:Cstruct.t;state:epoch_state;resumed:bool;client_app_secret:Cstruct.t;server_app_secret:Cstruct.t;}typeclient13_handshake_state=|AwaitServerHello13ofclient_hello*(group*dh_secret)list*Cstruct.t(* this is for CH1 ~> HRR ~> CH2 <~ WAIT SH *)|AwaitServerEncryptedExtensions13ofsession_data13*Cstruct.t*Cstruct.t*Cstruct.t|AwaitServerCertificateRequestOrCertificate13ofsession_data13*Cstruct.t*Cstruct.t*Cstruct.t|AwaitServerCertificate13ofsession_data13*Cstruct.t*Cstruct.t*signature_algorithmlistoption*Cstruct.t|AwaitServerCertificateVerify13ofsession_data13*Cstruct.t*Cstruct.t*signature_algorithmlistoption*Cstruct.t|AwaitServerFinished13ofsession_data13*Cstruct.t*Cstruct.t*signature_algorithmlistoption*Cstruct.t|Established13typeserver13_handshake_state=|AwaitClientHelloHRR13(* if we sent out HRR (also to-be-used for tls13-only) *)|AwaitClientCertificate13ofsession_data13*Cstruct.t*crypto_context*session_ticketoption*Cstruct.t|AwaitClientCertificateVerify13ofsession_data13*Cstruct.t*crypto_context*session_ticketoption*Cstruct.t|AwaitClientFinished13ofCstruct.t*crypto_context*session_ticketoption*Cstruct.t|AwaitEndOfEarlyData13ofCstruct.t*crypto_context*crypto_context*session_ticketoption*Cstruct.t|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:Cstruct.t;(* 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*Cstruct.t(* 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:Cstruct.t;(* the leftover fragment from TCP fragmentation *)read_closed:bool;write_closed:bool;}typeerror=[|`AuthenticationFailureofX509.Validation.validation_error|`NoConfiguredCiphersuiteofCiphersuite.ciphersuitelist|`NoConfiguredVersionsoftls_versionlist|`NoConfiguredSignatureAlgorithmofsignature_algorithmlist|`NoMatchingCertificateFoundofstring|`NoCertificateConfigured|`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|`NoCertificateConfigured->Fmt.stringppf"no certificate configured"|`CouldntSelectCertificate->Fmt.stringppf"couldn't select certificate"typeclient_hello_errors=[|`EmptyCiphersuites|`NotSetCiphersuitesofPacket.any_ciphersuitelist|`NoSupportedCiphersuiteofPacket.any_ciphersuitelist|`NotSetExtensionofclient_extensionlist|`NoSignatureAlgorithmsExtension|`NoGoodSignatureAlgorithmsofsignature_algorithmlist|`NoKeyShareExtension|`NoSupportedGroupExtension|`NotSetSupportedGroupofPacket.named_grouplist|`NotSetKeyShareof(Packet.named_group*Cstruct.t)list|`NotSubsetKeyShareSupportedGroupofPacket.named_grouplist*(Packet.named_group*Cstruct.t)list|`Has0rttAfterHRR|`NoCookie]letpp_client_hello_errorppf=function|`EmptyCiphersuites->Fmt.stringppf"empty ciphersuites"|`NotSetCiphersuitescs->Fmt.pfppf"ciphersuites not a set: %a"Fmt.(list~sep:(any", ")Ciphersuite.pp_any_ciphersuite)cs|`NoSupportedCiphersuitecs->Fmt.pfppf"no supported ciphersuite %a"Fmt.(list~sep:(any", ")Ciphersuite.pp_any_ciphersuite)cs|`NotSetExtension_->Fmt.stringppf"extensions not a set"|`NoSignatureAlgorithmsExtension->Fmt.stringppf"no signature algorithms extension"|`NoGoodSignatureAlgorithmssas->Fmt.pfppf"no good signature algorithm: %a"Fmt.(list~sep:(any", ")pp_signature_algorithm)sas|`NoKeyShareExtension->Fmt.stringppf"no keyshare extension"|`NoSupportedGroupExtension->Fmt.stringppf"no supported group extension"|`NotSetSupportedGroupgroups->Fmt.pfppf"supported groups not a set: %a"Fmt.(list~sep:(any", ")int)(List.mapPacket.named_group_to_intgroups)|`NotSetKeyShareks->Fmt.pfppf"key share not a set: %a"Fmt.(list~sep:(any", ")int)(List.map(fun(g,_)->Packet.named_group_to_intg)ks)|`NotSubsetKeyShareSupportedGroup(ng,ks)->Fmt.pfppf"key share not a subset of supported groups: %a@ keyshare %a"Fmt.(list~sep:(any", ")int)(List.mapPacket.named_group_to_intng)Fmt.(list~sep:(any", ")int)(List.map(fun(g,_)->Packet.named_group_to_intg)ks)|`Has0rttAfterHRR->Fmt.stringppf"has 0RTT after HRR"|`NoCookie->Fmt.stringppf"no cookie"typefatal=[|`NoSecureRenegotiation|`NoSupportedGroup|`NoVersionsoftls_any_versionlist|`ReaderErrorofReader.error|`NoCertificateReceived|`NoCertificateVerifyReceived|`NotRSACertificate|`KeyTooSmall|`SignatureVerificationFailedofstring|`SigningFailedofstring|`BadCertificateChain|`MACMismatch|`MACUnderflow|`RecordOverflowofint|`UnknownRecordVersionofint*int|`UnknownContentTypeofint|`CannotHandleApplicationDataYet|`NoHeartbeat|`BadRecordVersionoftls_any_version|`BadFinished|`HandshakeFragmentsNotEmpty|`InsufficientDH|`InvalidDH|`BadECDHofMirage_crypto_ec.error|`InvalidRenegotiation|`InvalidClientHelloofclient_hello_errors|`InvalidServerHello|`InvalidRenegotiationVersionoftls_version|`InappropriateFallback|`UnexpectedCCS|`UnexpectedHandshakeoftls_handshake|`InvalidCertificateUsage|`InvalidCertificateExtendedUsage|`InvalidSession|`NoApplicationProtocol|`HelloRetryRequest|`InvalidMessage|`Toomany0rttbytes|`MissingContentType|`Downgrade12|`Downgrade11|`WriteHalfClosed]letpp_fatalppf=function|`NoSecureRenegotiation->Fmt.stringppf"no secure renegotiation"|`NoSupportedGroup->Fmt.stringppf"no supported group"|`NoVersionsvs->Fmt.pfppf"no versions %a"Fmt.(list~sep:(any", ")pp_tls_any_version)vs|`ReaderErrorre->Fmt.pfppf"reader error: %a"Reader.pp_errorre|`NoCertificateReceived->Fmt.stringppf"no certificate received"|`NoCertificateVerifyReceived->Fmt.stringppf"no certificate verify received"|`NotRSACertificate->Fmt.stringppf"not a RSA certificate"|`KeyTooSmall->Fmt.stringppf"key too small"|`SignatureVerificationFailedmsg->Fmt.pfppf"signature verification failed: %s"msg|`SigningFailedmsg->Fmt.pfppf"signing failed: %s"msg|`BadCertificateChain->Fmt.stringppf"bad certificate chain"|`MACMismatch->Fmt.stringppf"MAC mismatch"|`MACUnderflow->Fmt.stringppf"MAC underflow"|`RecordOverflown->Fmt.pfppf"record overflow %u"n|`UnknownRecordVersion(m,n)->Fmt.pfppf"unknown record version %u.%u"mn|`UnknownContentTypec->Fmt.pfppf"unknown content type %u"c|`CannotHandleApplicationDataYet->Fmt.stringppf"cannot handle application data yet"|`NoHeartbeat->Fmt.stringppf"no heartbeat"|`BadRecordVersionv->Fmt.pfppf"bad record version %a"pp_tls_any_versionv|`BadFinished->Fmt.stringppf"bad finished"|`HandshakeFragmentsNotEmpty->Fmt.stringppf"handshake fragments not empty"|`InsufficientDH->Fmt.stringppf"insufficient DH"|`InvalidDH->Fmt.stringppf"invalid DH"|`BadECDHe->Fmt.pfppf"bad ECDH %a"Mirage_crypto_ec.pp_errore|`InvalidRenegotiation->Fmt.stringppf"invalid renegotiation"|`InvalidClientHelloce->Fmt.pfppf"invalid client hello: %a"pp_client_hello_errorce|`InvalidServerHello->Fmt.stringppf"invalid server hello"|`InvalidRenegotiationVersionv->Fmt.pfppf"invalid renegotiation version %a"pp_tls_versionv|`InappropriateFallback->Fmt.stringppf"inappropriate fallback"|`UnexpectedCCS->Fmt.stringppf"unexpected change cipher spec"|`UnexpectedHandshakehs->Fmt.pfppf"unexpected handshake %a"pp_handshakehs|`InvalidCertificateUsage->Fmt.stringppf"invalid certificate usage"|`InvalidCertificateExtendedUsage->Fmt.stringppf"invalid certificate extended usage"|`InvalidSession->Fmt.stringppf"invalid session"|`NoApplicationProtocol->Fmt.stringppf"no application protocol"|`HelloRetryRequest->Fmt.stringppf"hello retry request"|`InvalidMessage->Fmt.stringppf"invalid message"|`Toomany0rttbytes->Fmt.stringppf"too many 0RTT bytes"|`MissingContentType->Fmt.stringppf"missing content type"|`Downgrade12->Fmt.stringppf"downgrade 1.2"|`Downgrade11->Fmt.stringppf"downgrade 1.1"|`WriteHalfClosed->Fmt.stringppf"write half already closed"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=Cstruct.empty;alpn_protocol=common.alpn_protocol;session_id=Cstruct.empty;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)