My working unpac space for OCaml projects in development
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge opam/patches/tls

+23256
+17
vendor/opam/tls/.gitignore
··· 1 + _build/ 2 + *.native 3 + *.byte 4 + *.install 5 + .merlin 6 + 7 + main.ml 8 + .mirage.config 9 + mirage-unikernel*opam 10 + mirage/*/myocamlbuild.ml 11 + mirage/*/*ukvm 12 + mirage/*/tls_client 13 + mirage/*/tls_server 14 + Makefile 15 + key_gen.ml 16 + 17 + random/
+516
vendor/opam/tls/CHANGES.md
··· 1 + ## v2.0.3 (2025-09-26) 2 + 3 + * Provide an implementation which uses the Unix module (distributed with OCaml), 4 + based on the miou-unix implementation 5 + (#518 #443 @kit-ty-kate @dinosaure, fixes #517) 6 + 7 + ## v2.0.2 (2025-08-22) 8 + 9 + * put CERTIFICATE_UNKNOWN alert back (#516 @copy) 10 + * improve README (#514 @dinosaure) 11 + 12 + ## v2.0.1 (2025-04-14) 13 + 14 + * core, send_application_data: allocate much fewer data. previously, we 15 + allocated a lot to split the data into chunks of 2^14 - and did not have 16 + tail calls. the memory footprint, esp. for big amounts of data passed to 17 + send_application_data has changed now (#515 @hannesm @reynir) 18 + 19 + ## v2.0.0 (2025-02-05) 20 + 21 + * Use dune variants (mirage-ptime) instead of functorising over PCLOCK 22 + (#513 @hannesm) 23 + 24 + ## v1.0.4 (2024-10-28) 25 + 26 + * Removed links to nqsb (we're no longer in charge of that domain) 27 + (23c0deef586df4a1732efbf8d8da006111ca76e0, 28 + f6455e37513a74da63dc8819dfc8dd1aaebafb9a, fixes #512 reported by @msub2) 29 + 30 + ## v1.0.3 (2024-09-29) 31 + 32 + * tls-miou-unix: fix recursive call in read_in (#511 @dinosaure) 33 + 34 + ## v1.0.2 (2024-09-04) 35 + 36 + * tls-lwt: `read` now has an optional `?off:int` argument (#510 @hannesm) 37 + * Use the kdf package instead of hkdf (#509 @hannesm) 38 + 39 + ## v1.0.1 (2024-08-25) 40 + 41 + * tls-miou-unix: fix file descriptor leak (#508 @dinosaure) 42 + * tls-miou-unix: fix fuzz test (#507 @dinosaure) 43 + 44 + ## v1.0.0 (2024-08-21) 45 + 46 + * API breaking change: remove usage of Cstruct.t inside of TLS, use bytes 47 + and string instead (#497 by @art-w, @hannesm, @dinosaure, @reynir) 48 + Performance is up to 3x improved (bandwidth), 2x improvement for handshake/s 49 + on an Intel Core(TM) i7-5600U CPU @ 2.60GHz 50 + * FEATURE: add tls-miou-unix package, which adds miou support for TLS 51 + (#494 #503 @dinosaure) 52 + * FEATURE: tls-lwt and tls-async: allow TLS over an existing connection 53 + `Tls_lwt.client_of_channels : Tls.Config.client -> ?host:[`host] Domain_name.t -> Lwt_io.input_channel * Lwt_io.output_channel -> t Lwt.t` 54 + and 55 + `Tls_lwt.server_of_channels : Tls.Config.server -> Lwt_io.input_channel * Lwt_io.output_channel -> t Lwt.t` 56 + (#499 @art-w @MisterDA) 57 + * API breaking changes: revise errors - reduce the polymorphic variant 58 + in size, align it with RFC specified errors, be in parts more precise 59 + about errors, in other parts skip data (#505, @hannesm - fixes #491) 60 + NB: if you relied on a specific error constructor, please open an issue 61 + * Remove unused constructors from Packet.{alert_type, compression_methods, 62 + client_certificate_type, extension_type} (#505, @hannesm) 63 + NB: if you relied on specific constructors, please open an issue 64 + * API breaking change: Tls.Config.{server,client} now return a result 65 + type instead of raising an exception (#502, @hannesm, fixes #411) 66 + * FEATURE: add bench/speed.exe, a benchmark for bandwidth (for different 67 + ciphersuites) and handshakes (different key exchanges and private keys) 68 + (#500 @hannesm @dinosaure @reynir) 69 + * BUGFIX: tests/feedback.exe update with TLS 1.3 semantics, run as test 70 + (#501, @hannesm - reported by @dinosaure) 71 + 72 + ## v0.17.5 (2024-05-14) 73 + 74 + * tls: documentation: clarify send_application_data (#492 @reynir) 75 + * BUGFIX: tls: export_key_material was wrong for the server side on TLS 1.3, 76 + reported in robur-coop/miragevpn#181 by @reynir, fix in #495 @hannesm 77 + * FEATURE: tls: add channel_binding (RFC 5929, RFC 9266) support (tls_unique, 78 + tls_exporter, tls_server_endpoint), requested by @Neustradamus in #484, added 79 + in #496 by @hannesm 80 + 81 + ## v0.17.4 (2024-03-26) 82 + 83 + * tls: handle half-closed connection properly: a received CLOSE_NOTIFY does not 84 + lead to a CLOSE_NOTIFY to be sent (a `send_close_notify` sends it explicitly) 85 + (#488 @hannesm) 86 + * tls: modify return type of `handle_tls` - the Alert is now in the right hand 87 + side, and `` `Eof `` is explicit in the second part of the tuple 88 + (#488 @hannesm) 89 + * tls: remove `can_handle_appdata`, the function `handshake_in_progress` is 90 + available (#488 @hannesm) 91 + * tls-mirage: avoid exceptions in reneg and rekey (#487 @hannesm) 92 + * tls: remove HEARTBEAT decoding - HEARTBEAT was never supported in this 93 + library, the decoder was superfluous (#487 @hannesm) 94 + * tls-mirage: provide `underlying : flow -> FLOW.flow` (#487 @hannesm, 95 + fixes #425 @dinosaure) 96 + * tls-mirage: implement mirage-flow 4 API (`val shutdown`) (#488 @hannesm) 97 + * tls-eio: adapt to half-closed connections (#488 @talex5) 98 + * tls-eio: implement Eio.Resource.Close (#489 @paurkedal, reviewed by @talex5) 99 + 100 + ## v0.17.3 (2023-11-20) 101 + 102 + * tls: provide Engine.export_key_material, which implements RFC 5705 (and 8446) 103 + TLS EKM (#482 @hannesm) 104 + * tls: fix protocol_version in Engine.epoch (TLS 1.3 always pretended TLS 1.0) 105 + (#482 @hannesm) 106 + * tls: add the side (`` `Client `` or `` `Server ``) to epoch_data 107 + (#482 @hannesm) 108 + * BREAKING tls: Engine.epoch - return result instead of custom variant 109 + (#483 @hannesm) 110 + 111 + ## v0.17.2 (2023-09-24) 112 + 113 + * tls-eio: update to eio 0.12 (#479 @talex5) 114 + 115 + ## v0.17.1 (2023-07-03) 116 + 117 + * tls-async: update to 0.16 series (#476 @tmcgilchrist, review by @torinnd) 118 + * avoid Cstruct.copy (@hannesm) 119 + 120 + ## v0.17.0 (2023-03-01) 121 + 122 + * tls-async: remove ocaml < 5.0.0 constraint (#471 #474 @hannesm) 123 + * remove dependency on ppx, especially ppx_cstruct and ppx_sexp_conv across 124 + the libraries (#473 @hannesm, discussion in #472) 125 + 126 + ## v0.16.0 (2023-02-14) 127 + 128 + * BREAKING: new opam package tls-lwt (formerly tls.lwt), in dune: 129 + (libraries tls.lwt) should now be libraries (tls-lwt) 130 + (#468 @hannesm, reported #449 by @mbacarella) 131 + * tls: update to mirage-crypto 0.11 API (#468 @hannesm) 132 + * tls: relax SignatureAlgorithms extension handling to allow OpenSSL 133 + interoperability tests with TLS 1.0 and TLS 1.1 (#469 @hannesm) 134 + * tls: remove Utils.filter_map and and Utils.option, use Stdlib instead (#455 135 + @hannesm) 136 + * tls: do not globally open Utils (#455 @hannesm) 137 + * tls: export log source of Tracing module (#461 @bikallem) 138 + * tls: remove unused ciphersuites to reduce binary size (#467 @hannesm) 139 + * tls-lwt: do not catch out of memory exception (#469 @hannesm) 140 + * tls-eio: add fuzz testing using crowbar (#456 #463 @talex5) 141 + * tls-eio: update to eio 0.7 (#456 @talex5) 142 + * tls-eio: fix test for develop with vendoring (#462 @bikallem) 143 + 144 + ## v0.15.5 (2022-10-25) 145 + 146 + * tls-eio release only: fix end-of-file handling (#454 @talex5), avoid 147 + deprecation warnings (#454 @hannesm) 148 + 149 + ## v0.15.4 (2022-09-27) 150 + 151 + * New package tls-eio (#451 @talex5) 152 + * Tls_async: expose tls_handler (#448 @mbacarella, reviewed by @torinnd) 153 + 154 + ## v0.15.3 (2022-03-29) 155 + 156 + * Upgrade to v0.15 of Jane Street packages (#444 @bcc32) 157 + * Use cmdliner 1.1.0 in lwt/examples (#445 @hannesm) 158 + 159 + ## v0.15.2 (2021-11-14) 160 + 161 + * Tls_async: drop dependency on async_find, now trust anchors in a directory 162 + are not recursively read - aligns it with the lwt and mirage implementations 163 + (#442 @torinnd) 164 + 165 + ## v0.15.1 (2021-10-29) 166 + 167 + * Tls_lwt: avoid exception if connect is executed with a non-host name string 168 + (e.g. an IP address) (#441 @hannesm) 169 + * Bugfix: log a warning if certificate decoding fails (#441 @hannesm) 170 + * Remove rresult dependency (#441 @hannesm) 171 + 172 + ## v0.15.0 (2021-10-07) 173 + 174 + * Adapt to x509 0.15.0 changes (#440 @hannesm) 175 + 176 + ## v0.14.1 (2021-09-13) 177 + 178 + * Bugfix: do not filter signature_algorithms based on server certificate. Since 179 + signature_algorithms is also used for client authentication (as 180 + SignatureAlgorithms extension in CertificateVerify), previously the client 181 + needed the same key type as the server. 182 + Discovered in https://github.com/roburio/albatross/commit/df434da0e531e1b0c8091a0fc82e8b37ed319e7a 183 + 184 + ## v0.14.0 (2021-08-02) 185 + 186 + * Breaking: peer_name (in config and epoch data, also own_name) is now a 187 + [`host] Domain_name.t instead of a string. (#434 #438 @torinnd @hannesm) 188 + * Add a X509_async module (#435 @torinnd) 189 + * Client and server constructor log messages are on the debug level (#436 190 + reported by @talex5, fix by @hannesm) 191 + * Adapt to cstruct 6.0.0 API (Cstruct.len is deprecated) #439 @hannesm 192 + 193 + ## v0.13.2 (2021-06-04) 194 + 195 + * New package tls-async that provides an effectful layer of TLS using async. 196 + (#432, @torinnd, @dinosaure, @kit-ty-kate, reviews by @hannesm @avsm @seliopou) 197 + 198 + ## v0.13.1 (2021-04-22) 199 + 200 + * Breaking: use deriving sexp_of instead of sexp. Constructing a state from 201 + a sexp has not been supported (lead to exception), and is now removed 202 + (#430 by @torinnd, continued in #431 by @hannesm) 203 + * Bugfix: TLS 1.3 client authentication with certificate, client side. This 204 + used to work accidentally before 0.13.0 changed the signature algorithms 205 + handling, now the right signature algorithm (as requested by server) is used. 206 + (#431 @hannesm, @talex5 reported https://github.com/mirage/capnp-rpc/pull/228) 207 + * adapt to x509 0.13.0 and mirage-crypto-ec 0.10.0 changes (#431 @hannesm) 208 + 209 + ## v0.13.0 (2021-04-14) 210 + 211 + * Remove static RSA and CBC ciphersuites from default configuration. The 212 + default configuration now includes FFDHE and ECDHE key exchanges with RSA or 213 + ECDSA/EdDSA certificates, and AEAD ciphers 214 + (AES-GCM, AES-CCM, ChaCha20-Poly1305) (#429 by @hannesm) 215 + * Remove SHA1 from signature_algorithms in the default configuration 216 + (#429 by @hannesm) 217 + * Support ECDSA and EdDSA certificates and private keys via x509 0.12.0 and 218 + mirage-crypto-ec (#428 by @hannesm) 219 + Breaking changes: 220 + - the second part of type Tls.Config.certchain is now a X509.Private_key.t 221 + (previously Mirage_crypto_pk.Rsa.priv) 222 + - the type aliases X509_lwt.priv and X509_lwt.authenticator have been removed 223 + * Use mirage-crypto-ec instead of fiat-p256 and hacl_x25519 for elliptic curve 224 + support - this adds P384 and P521 ECDH support (#428 by @hannesm) 225 + * Remove custom Monad implementation, use Result and Rresult instead 226 + (#429 by @hannesm) 227 + * Remove Utils.Cs submodule, use Cstruct API instead (#429 by @hannesm) 228 + * Breaking: Tls.Engine.ret type is now a result instead of a custom variant type 229 + (#429 by @hannesm) 230 + * Breaking: Tls_lwt.Unix.epoch results in (Tls.Core.epoch_data, unit) result - 231 + it was a custom error type previously (#429 by @hannesm) 232 + 233 + ## v0.12.8 (2020-12-08) 234 + 235 + * Re-add ECPointFormats hello extension (both client and server) to avoid 236 + handshake failures with Go's TLS stack (RFC 8422 makes it optional, but go 237 + (1.15.5) requires it) - reported by @jeffa5 at 238 + https://discuss.ocaml.org/t/strange-prohibited-tls-1-2-cipher-suite-9d-issue/ 239 + fix by @hannesm #424 240 + 241 + ## v0.12.7 (2020-12-04) 242 + 243 + * Tls.lwt: make the receive buffer connection-local to avoid potential data 244 + races (#422 by @dinosaure) 245 + * Tls_mirage: remove unneeded type alias (@hannesm) 246 + * Add Tls.Config.Ciphers.http2 - a list of ciphersuites allowed to be negotiated 247 + for HTTP2 sessions (#423 by @jeffa5) 248 + 249 + ## v0.12.6 (2020-11-06) 250 + 251 + * OCaml 4.12 support (#421 @kit-ty-kate) 252 + 253 + ## v0.12.5 (2020-09-22) 254 + 255 + * Rename length to v_length to be compatible with cstruct 6.0.0 (#419 @dinosaure) 256 + 257 + ## v0.12.4 (2020-08-08) 258 + 259 + * handshake_server13: demote group and cipher log level (#417 by @xguerin) 260 + * tls_lwt: register printers for Tls_alert and Tls_failure (#418 by @hannesm) 261 + 262 + ## v0.12.3 (2020-07-04) 263 + 264 + * Adapt to new GCM and CCM API of mirage-crypto (#416 by @hannesm) 265 + * Add support for ChaCha20/Poly1305 ciphersuite (#416 by @hannesm) 266 + 267 + ## v0.12.2 (2020-06-20) 268 + 269 + * tls_lwt again calls Mirage_crypto_rng_lwt.initialize () -- which is since 270 + mirage-crypto-rng 0.8 no longer inside the lwt monad, and safe to be called 271 + multiple times and on top level (#415 by @hannesm) 272 + 273 + ## v0.12.1 (2020-06-12) 274 + 275 + in #414 by @hannesm 276 + * Drop support for RC4 ciphersuite 277 + * Raise lower TLS version in default configuration to 1.2 278 + * tls_lwt no longer calls Mirage_crypto_rng_unix.initialize -- this needs to be 279 + done in the application, inside Lwt_main.run: 280 + `Mirage_crypto_rng_lwt.initialize () >>= fun () ->` 281 + * Support ECDHE ciphersuites in TLS 1.2 and below as specified in RFC 8422 282 + (requested in #413 by @ryanakca, also in #362 by @orbitz @annubiz) 283 + * drop "TLS_" prefix from ciphersuite constructors 284 + * BUGFIX: TLS client (<= 1.2) assembling an empty Certificate message 285 + (noticed in #413, present since 0.12.0 release) 286 + * Cleanup Packet.any_ciphersuite list (remove ARIA, CAMELLIA, KRB5, EXPORT) 287 + * Adapt interoperability test scripts with TLS 1.3 support 288 + 289 + ## v0.12.0 (2020-05-12) 290 + 291 + in #405 by @hannesm 292 + * TLS 1.3 support 293 + * Tracing now uses the logs library (log source tls.tracing on debug level) 294 + * bugfix for padding in ClientHello, which computed wrong length 295 + * bugfix hs_fragments to be set before executing the protocol handling logic 296 + * bugfix guard RSA signature with an Insufficient_key handler, which may occur 297 + when using an RSA key which size is too small for the used digest algorithm 298 + 299 + ## v0.11.1 (2020-04-09) 300 + 301 + * Adapt to X509.0.11.0 API changes (#412) 302 + 303 + ## v0.11.0 (2020-03-12) 304 + 305 + * use dune as build system (#407) 306 + * BREAKING split into tls and tls-mirage opam packages (#407) 307 + * BREAKING use mirage-crypto instead of nocrypto (#407) 308 + 309 + ## v0.10.6 (2020-01-23) 310 + 311 + * adapt to x509 0.9.0 interface: certificate revocation lists can now be passed 312 + to the authenticator in Tls_mirage and X509_lwt; also a list of hash 313 + algorithms to be used for certificate signature verification can be passed to 314 + the authenticator 315 + * adapt to lwt 5.0.0 316 + 317 + ## v0.10.5 (2019-11-01) 318 + 319 + * adapt to mirage-flow 2.0.0, mirage-clock 3.0.0, mirage-kv 3.0.0 interfaces (#401 @hannesm) 320 + 321 + ## 0.10.4 (2019-08-15) 322 + 323 + * tls_lwt: avoid double close by checking in the default `close` callback of 324 + `Lwt_io.make` whether the underlying file descriptor has been closed already. 325 + (reported and discussed by @hcarty in #395, merged #397) 326 + 327 + ## 0.10.3 (2019-07-26) 328 + 329 + * support x509 0.7.0+ 330 + * remove dependency on Astring (was only used in the lwt-starttls example) 331 + 332 + ## 0.10.2 (2019-04-02) 333 + 334 + * support for cstruct 4.0.0+ 335 + * remove support for < 4.04.2 (same as x509 in master) 336 + * remove result (part of 4.03.0) 337 + * enhance mirage/example2 to work on more platforms than unix 338 + 339 + ## 0.10.1 (2019-02-28) 340 + 341 + * tls-mirage: fix compilation 342 + 343 + ## 0.10.0 (2019-02-28) 344 + 345 + * tls: fix extensions length (used to include the 2 byte extension length field) 346 + if padding is inserted (introduced on May 5, 2014 in #73) 347 + * tls-mirage: adapt to mirage-kv 2.0.0 API (#384, @samoht) 348 + 349 + ## 0.9.3 (2019-01-07) 350 + 351 + * tls: do not require client sent ciphersuites to be a proper set 352 + (interoperability with some android devices) 353 + * tls_lwt: delay error from writing to peer while reading, record errors only 354 + if state is active (fixes #347) 355 + * migrate opam file to opam 2.0 format 356 + 357 + ## 0.9.2 (2018-08-24) 358 + 359 + * compatibility with ppx_sexp_conv >v0.11.0 (#381), required for 4.07.0 360 + * support ALPN (#378, @bobbypriambodo) 361 + 362 + ## 0.9.1 (2018-02-26) 363 + 364 + * Tls_lwt: use Tls.Config instead of Config directly to avoid polluting imported 365 + names (#376, @rgrinberg) 366 + 367 + ## 0.9.0 (2017-12-23) 368 + 369 + * renegotiation semantics (#375) 370 + allow acceptable_ca, authenticator, and own_cert to be updated (Config.with_x) 371 + semantics of reneg is blocking 372 + `{Tls_lwt.Unix|Tls_mirage}.reneg ~drop:bool` drops data of earlier epoch 373 + * implement acceptable_ca (#332, @reynir) 374 + * fix client renegotiation with ExtendedMasterSecret (#373, broken since 0.7.0) 375 + * Config.client can get ~peer_name (#373) 376 + * Asn.Time.t is Ptime.t now (asn1-combinators.0.2.0, x509.0.6.0, #372) 377 + * cleanups (#360, #363, #369, @rgrinberg) 378 + * remove 3DES CBC SHA from default ciphers (#359) 379 + 380 + ## 0.8.0 (2017-02-01) 381 + 382 + * lwt: in Unix.client_of_fd the named argument host is now optional (#336) 383 + * mirage: in client_of_flow the (positional) hostname argument is now optional (#336) 384 + * mirage: adapt to PCLOCK interface (@mattgray #329 #331) 385 + * build system migrated from oasis to topkg (#342) 386 + * mirage: adapt to MirageOS3 (@yomimono @samoht #338 #349 #350 #351 #353) 387 + * lwt: do not crash on double close (@vbmithr #345) 388 + * fixed docstring typos (@mor1 #340) 389 + 390 + ## 0.7.1 (2016-03-21) 391 + 392 + * remove camlp4 dependency (use cstruct ppx and sexplib ppx instead) 393 + * sort client extensions, there are servers which dislike an extension without 394 + data at the end, thus try to send extensions with data at the end (#319) 395 + * initial GCM support (#310) 396 + * fix `hs_can_handle_appdata` (#315): 397 + Initially we allowed application data always after the first handshake. 398 + 399 + Turns out, between CCS and Finished there is new crypto_context in place 400 + which has not yet been authenticated -- bad idea to accept application data 401 + at that point (beginning of 2015 in OCaml TLS). 402 + 403 + The fix was to only allow application data in Established state (and block 404 + in Tls_lwt/Tls_mirage when the user requested renegotiation) (December 2015 405 + in OCaml-TLS). 406 + 407 + Renegotiation was also turned off by default when we introduced resumption 408 + (mid October 2015): both features together (without mitigating via session 409 + hash) allow the triple handshake. 410 + 411 + It turns out, the server side can happily accept application data from the 412 + other side when it just sent a HelloRequest (and waits for the ClientHello; 413 + same is true for the client side, waiting for the ServerHello in 414 + renegotiation case might be interleaved with application data) to let the 415 + client initiate a new handshake. By this commit, OCaml-TLS allows 416 + application data then. 417 + 418 + In the end, it is a pretty academic thing anyways, since nobody uses 419 + renegotiation with OCaml-TLS in the field. 420 + * during verification of a digitally signed: checked that the used hash 421 + algorithm is one of the configured ones (#313) 422 + * unify return type of handshake and change cipher spec handler (#314) 423 + * separate client and server extensions (#317) 424 + * type equality (no longer generative error type), use result (#318) 425 + * removed Printer (was barely useful) 426 + 427 + ## 0.7.0 (2015-12-04) 428 + 429 + * session resumption (via session ID) support (#283) 430 + Config contains `session_cache : SessionID.t -> epoch_data option` 431 + and `cached_session : epoch_data option` 432 + * session hash and extended master secret (RFC 7627) support (#287) 433 + 434 + ### semantic changes 435 + * disable renegotiation by default (#300) 436 + * blocking semantics (both Mirage and Lwt) while renegotiating (#304) 437 + * `Engine.handshake_in_progress` no longer exist 438 + * `Hex_fingerprint / `Fingerprint authenticators no longer exist 439 + * Mirage X509 does no longer prefix keys and trust anchors with "tls/" in the path 440 + 441 + ### minor fixes 442 + * fix concurrent read/write in tls_mirage (#303) 443 + * expose own_random and peer_random in epoch_data (@cfcs, #297) 444 + * public key pinning (X509_lwt) via `Hex_key_fingerprint / `Key_fingerprint (#301) 445 + * certificate chain and peer certificate are exposed via epoch_data (new path-building X.509 interface) 446 + 447 + ## 0.6.0 (2015-07-02) 448 + 449 + * API: dropped 'perfect' from forward secrecy in Config.Ciphers: 450 + fs instead of pfs, fs_of instead of pfs_of 451 + * API: type epoch_data moved from Engine to Core 452 + * removed Cstruct_s now that cstruct (since 1.6.0) provides 453 + s-expression marshalling 454 + * require at least 1024 bit DH group, use FFDHE 2048 bit DH group 455 + by default instead of oakley2 (logjam) 456 + * more specific alerts: 457 + - UNRECOGNIZED_NAME: if hostname in SNI does not match 458 + - UNSUPPORTED_EXTENSION: if server hello has an extension not present in 459 + client hello 460 + - ILLEGAL_PARAMETER: if a parse error occured 461 + * encrypt outgoing alerts 462 + * fix off-by-one in handling empty TLS records: if a record is less than 5 463 + bytes, treat as a fragment. exactly 5 bytes might already be a valid 464 + application data frame 465 + 466 + ## 0.5.0 (2015-05-02) 467 + 468 + * updates to extension enum (contributed by Dave Garrett #264) 469 + * removed entropy feeding (done by nocrypto) #265 470 + * Tls_lwt file descriptor lifecycle: not eagerly close file descriptors #266 471 + 472 + ## 0.4.0 (2015-03-19) 473 + 474 + * client authentication (both client and server side) 475 + * server side SNI configuration (see sni.md) 476 + * SCSV server-side downgrade prevention (by Gabriel de Perthuis @g2p #5) 477 + * remove RC4 ciphers from default config #8 478 + * support for AEAD ciphers, currently CCM #191 479 + * proper bounds checking of handshake fragments #255 480 + * disable application data between CCS and Finished #237 481 + * remove secure renegotiation configuration option #256 482 + * expose epoch in mirage interface, implement 2.3.0 API (error_message) 483 + * error reporting (type failure in engine.mli) #246 484 + * hook into Lwt event loop to feed RNG #254 485 + 486 + ## 0.3.0 (2014-12-21) 487 + 488 + * X509_lwt provides `Fingerprints and `Hex_fingerprints constructor for 489 + checking fingerprints of certificates instead of trusting trust 490 + anchors #206 #207 491 + * client configuration requires an authenticator #202 492 + * server certificate must be at least Config.min_rsa_key_size bits 493 + * expose epoch via lwt interface #208 494 + * mirage-2.2.0 compatibility #212 495 + * cleanups of mirage interface #213 496 + * nocrypto-0.3.0 compatibility #194 #209 #210 497 + 498 + ## 0.2.0 (2014-10-30) 499 + 500 + * distinguish between supported hash and mac algorithms (using Nocrypto.Hash) 501 + and those which may occur on the wire #189 502 + * expose trust anchor when authenticating certificate (requires x509 >=0.2) #178 503 + * information about the active session is exposed via epoch : state -> epoch 504 + * distinguish between supported ciphersuites (type ciphersuite) and 505 + known ciphersuites (type any_ciphersuite) #173 506 + * distinguish between supported versions by the stack (type tls_version) 507 + and readable versions (tls_any_version), which might occur in a tls 508 + record or client_hello read from the network #179 #172 509 + * support > TLS-1.2 client hellos (as reported by ssllabs.com #161) 510 + * support iOS 6 devices (who propose NULL ciphers - reported in #160) 511 + * send minimal protocol version in record layer of client hello 512 + (maximum version is in the client hello itself) (RFC5246, E.1) #165 513 + 514 + ## 0.1.0 (2014-07-08) 515 + 516 + * initial beta release
+23
vendor/opam/tls/LICENSE.md
··· 1 + Copyright (c) 2014, David Kaloper and Hannes Mehnert 2 + All rights reserved. 3 + 4 + Redistribution and use in source and binary forms, with or without modification, 5 + are permitted provided that the following conditions are met: 6 + 7 + * Redistributions of source code must retain the above copyright notice, this 8 + list of conditions and the following disclaimer. 9 + 10 + * Redistributions in binary form must reproduce the above copyright notice, this 11 + list of conditions and the following disclaimer in the documentation and/or 12 + other materials provided with the distribution. 13 + 14 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+89
vendor/opam/tls/README.md
··· 1 + ## TLS - Transport Layer Security purely in OCaml 2 + 3 + %%VERSION%% 4 + 5 + Transport Layer Security (TLS) is probably the most widely deployed security 6 + protocol on the Internet. It provides communication privacy to prevent 7 + eavesdropping, tampering, and message forgery. Furthermore, it optionally 8 + provides authentication of the involved endpoints. TLS is commonly deployed for 9 + securing web services ([HTTPS](http://tools.ietf.org/html/rfc2818)), emails, 10 + virtual private networks, and wireless networks. 11 + 12 + TLS uses asymmetric cryptography to exchange a symmetric key, and optionally 13 + authenticate (using X.509) either or both endpoints. It provides algorithmic 14 + agility, which means that the key exchange method, symmetric encryption 15 + algorithm, and hash algorithm are negotiated. 16 + 17 + Read our [Usenix Security 2015 paper](https://www.usenix.org/conference/usenixsecurity15/technical-sessions/presentation/kaloper-mersinjak) for further details. 18 + 19 + ## Documentation 20 + 21 + [API documentation](https://mirleft.github.io/ocaml-tls/doc) 22 + 23 + ## Installation 24 + 25 + `opam install tls` will install this library. 26 + 27 + You can also build this locally by conducting the steps: 28 + 29 + ```bash 30 + opam install --deps-only -t . # or a named package instead of `.` - i.e. ./tls-lwt.opam 31 + dune build --profile=release # you can also put a package list here, i.e. tls,tls-lwt -- you can also use `@all` target to compile examples as well 32 + ``` 33 + 34 + ## Usage 35 + 36 + The core of `ocaml-tls` (the opam package `tls`, available in the `lib` 37 + subdirectory) is an library independent of schedulers and does not perform any 38 + I/O operations. The library is designed so that a `Tls.Engine.state` state 39 + informs you of when to write and when to feed more data. It does not use 40 + mutation and is in a value-passing style (so, read data and state is the input, 41 + and data to be sent or presented to the upper layer, and state is the output). 42 + 43 + There are therefore `ocaml-tls` derivations with different schedulers that 44 + perform read and write operations. These derivations offer an interface similar 45 + to what an SSL socket (like [ssl][ssl]) can offer. 46 + - [lwt](https://ocsigen.org/lwt/latest/manual/manual): `tls-lwt` proposes to 47 + initiate a TLS flow with `Lwt_io.{input,output}_channel` from a Unix socket. 48 + It can also propose an abstract type `Tls_lwt.Unix.t` (which can be created 49 + from a Unix socket) associated with a `Tls_lwt.Unix` interface similar to a 50 + Unix socket. 51 + - [miou](https://github.com/robur-coop/miou): `tls-miou-unix` proposes a TLS 52 + flow via an abstract type `Tls_miou_unix.t` and an interface similar to a Unix 53 + socket from a `Miou_unix.file_descr` socket. 54 + - [MirageOS](https://mirageos.org): `tls-mirage` proposes a composition 55 + of a [`Mirage_flow.S`](https://github.com/mirage/mirage-flow/) module to 56 + obtain a new `Mirage_flow.S` (corresponding to the TLS layer) which uses the 57 + lwt scheduler. 58 + - [eio](https://github.com/ocaml-multicore/eio): `tls-eio` proposes the creation 59 + of an _eio flow_ from another _eio flow_. 60 + - [async](https://github.com/janestreet/async): `tls-async` proposes a TLS flow 61 + via `Async.{Reader,Writer}.t` from a `Async.Socket`. 62 + 63 + Depending on the scheduler you choose, you should choose one of these 64 + `ocaml-tls` derivations, distributed in the mentioned opam packages (tls-lwt, 65 + tls-mirage, tls-eio, tls-async). Each one takes advantage of what the scheduler 66 + used has to offer. 67 + 68 + ### Composability 69 + 70 + `ocaml-tls` can also be used as it is in order to be able to compose with other 71 + protocols without choosing a scheduler. This is the case, for example, with 72 + [sendmail.starttls][sendmail], which composes the SMTP and TLS protocols. The 73 + user can also be more selective about the use of certificates involved in a TLS 74 + connection, as [albatross][albatross] can offer in its transactions between 75 + clients and the server. 76 + 77 + When seen as OCaml values, the critical elements that enable instantiation of a 78 + TLS connection can be very finely controlled. 79 + 80 + ### Portability 81 + 82 + ocaml-tls is currently used for [MirageOS unikernels](https://mirageos.org), 83 + which makes it portable and available on many systems (even the most restricted 84 + ones such as [Solo5](https://github.com/solo5/solo5) as long as OCaml is 85 + available on them. 86 + 87 + [sendmail]: https://github.com/mirage/colombe 88 + [albatross]: https://github.com/robur-coop/albatross 89 + [ssl]: https://github.com/savonet/ocaml-ssl
+5
vendor/opam/tls/async/dune
··· 1 + (library 2 + (name tls_async) 3 + (public_name tls-async) 4 + (preprocess (pps ppx_jane)) 5 + (libraries async core cstruct-async mirage-crypto-rng mirage-crypto-rng.unix tls))
+15
vendor/opam/tls/async/examples/dune
··· 1 + (executable 2 + (name test_client) 3 + (modules test_client) 4 + (public_name tls-test-client) 5 + (package tls-async) 6 + (preprocess (pps ppx_jane)) 7 + (libraries async core core_unix.command_unix tls-async)) 8 + 9 + (executable 10 + (name test_server) 11 + (modules test_server) 12 + (public_name tls-test-server) 13 + (package tls-async) 14 + (preprocess (pps ppx_jane)) 15 + (libraries async core core_unix.command_unix tls-async))
+34
vendor/opam/tls/async/examples/test_client.ml
··· 1 + open! Core 2 + open! Async 3 + open Deferred.Or_error.Let_syntax 4 + 5 + let config = match Tls.Config.client ~authenticator:(fun ?ip:_ ~host:_ _ -> Ok None) () with 6 + | Ok cfg -> cfg 7 + | Error `Msg msg -> invalid_arg msg 8 + 9 + let test_client () = 10 + let host = "127.0.0.1" in 11 + let port = 8443 in 12 + let hnp = Host_and_port.create ~host ~port in 13 + let%bind (_ : Tls_async.Session.t), rd, wr = 14 + (* we can't build a [[ `host ] Domain_name.t] from an IP address *) 15 + let host = None in 16 + Tls_async.connect config (Tcp.Where_to_connect.of_host_and_port hnp) ~host 17 + in 18 + let req = 19 + String.concat 20 + ~sep:"\r\n" 21 + [ "GET / HTTP/1.1"; "Host: " ^ host; "Connection: close"; ""; "" ] 22 + in 23 + Writer.write wr req; 24 + let%bind () = Writer.flushed wr |> Deferred.ok in 25 + let%bind () = 26 + match%map Reader.read_line rd |> Deferred.ok with 27 + | `Ok str -> print_endline str 28 + | `Eof -> print_endline "Eof reached" 29 + in 30 + Writer.close wr |> Deferred.ok 31 + ;; 32 + 33 + let cmd = Command.async_or_error ~summary:"test client" (Command.Param.return test_client) 34 + let () = Command_unix.run cmd
+64
vendor/opam/tls/async/examples/test_server.ml
··· 1 + open! Core 2 + open! Async 3 + 4 + let server_cert = "./certificates/server.pem" 5 + let server_key = "./certificates/server.key" 6 + 7 + let serve_tls ~low_level port handler = 8 + let%bind certificate = 9 + Tls_async.X509_async.Certificate.of_pem_file server_cert |> Deferred.Or_error.ok_exn 10 + in 11 + let%bind priv_key = 12 + Tls_async.X509_async.Private_key.of_pem_file server_key |> Deferred.Or_error.ok_exn 13 + in 14 + let config = 15 + match Tls.Config.( 16 + server 17 + ~version:(`TLS_1_0, `TLS_1_2) 18 + ~certificates:(`Single (certificate, priv_key)) 19 + ~ciphers:Ciphers.supported 20 + ()) 21 + with 22 + | Ok cfg -> cfg 23 + | Error `Msg msg -> invalid_arg msg 24 + in 25 + let where_to_listen = Tcp.Where_to_listen.of_port port in 26 + let on_handler_error = `Ignore in 27 + if low_level then 28 + Tcp.Server.create 29 + ~on_handler_error 30 + where_to_listen 31 + (fun sa -> 32 + printf !"connection establised from %{Socket.Address.Inet} starting TLS\n" sa; 33 + Tls_async.upgrade_server_handler ~config (handler sa)) 34 + else 35 + Tls_async.listen ~on_handler_error config where_to_listen handler 36 + ;; 37 + 38 + let test_server ~low_level port = 39 + let handler (_ : Socket.Address.Inet.t) (_ : Tls_async.Session.t) rd wr = 40 + let pipe = Reader.pipe rd in 41 + let rec read_from_pipe () = 42 + (match%map Pipe.read pipe with 43 + | `Ok line -> Writer.write wr line 44 + | `Eof -> ()) 45 + >>= read_from_pipe 46 + in 47 + read_from_pipe () 48 + in 49 + serve_tls ~low_level port handler 50 + ;; 51 + 52 + let cmd = 53 + let open Command.Let_syntax in 54 + Command.async 55 + ~summary:"test server" 56 + (let%map_open port = anon ("PORT" %: int) 57 + and low_level = flag "-low-level" no_arg ~doc:"set up Tcp.server directly" in 58 + fun () -> 59 + let open Deferred.Let_syntax in 60 + let%bind server = test_server ~low_level port in 61 + Tcp.Server.close_finished server) 62 + ;; 63 + 64 + let () = Command_unix.run cmd
+200
vendor/opam/tls/async/io.ml
··· 1 + open! Core 2 + open! Async 3 + include Io_intf 4 + 5 + module Tls_error = struct 6 + module Alert = struct 7 + type t = Tls.Packet.alert_type 8 + let sexp_of_t a = 9 + Sexplib.Sexp.Atom (Tls.Packet.alert_type_to_string a) 10 + end 11 + module Fail = struct 12 + type t = Tls.Engine.failure 13 + let sexp_of_t a = 14 + Sexplib.Sexp.Atom (Tls.Engine.string_of_failure a) 15 + end 16 + type t = 17 + | Tls_alert of Alert.t 18 + (** [Tls_alert] exception received from the other endpoint *) 19 + | Tls_failure of Fail.t 20 + (** [Tls_failure] exception while processing incoming data *) 21 + | Connection_closed 22 + | Connection_not_ready 23 + | Unexpected_eof 24 + | Unable_to_renegotiate 25 + | Unable_to_update_key 26 + [@@deriving sexp_of] 27 + end 28 + 29 + module Make (Fd : Fd) : S with module Fd := Fd = struct 30 + open Deferred.Or_error.Let_syntax 31 + 32 + module State = struct 33 + type t = 34 + | Active of Tls.Engine.state 35 + | Eof 36 + | Error of Tls_error.t 37 + end 38 + 39 + type t = 40 + { fd : Fd.t 41 + ; mutable state : State.t 42 + ; mutable linger : string option 43 + ; recv_buf : bytes 44 + } 45 + 46 + let tls_error = Fn.compose Deferred.Or_error.error_s Tls_error.sexp_of_t 47 + 48 + let rec read_react t = 49 + let handle tls buf = 50 + match Tls.Engine.handle_tls tls buf with 51 + | Ok (state, eof, `Response resp, `Data data) -> 52 + t.state 53 + <- (match eof with 54 + | None -> Active state 55 + | Some `Eof -> Eof); 56 + let%map () = 57 + match resp with 58 + | None -> return () 59 + | Some resp -> Fd.write_full t.fd resp 60 + in 61 + `Ok data 62 + | Error (alert, `Response resp) -> 63 + t.state <- Error (match alert with `Alert a -> Tls_alert a | f -> Tls_failure f); 64 + let%bind () = Fd.write_full t.fd resp in 65 + read_react t 66 + in 67 + match t.state with 68 + | Error e -> tls_error e 69 + | Eof -> return `Eof 70 + | Active _ -> 71 + let%bind n = Fd.read t.fd t.recv_buf in 72 + (match t.state, n with 73 + | Active _, `Eof -> 74 + t.state <- Eof; 75 + return `Eof 76 + | Active tls, `Ok n -> handle tls (Stdlib.Bytes.sub_string t.recv_buf 0 n) 77 + | Error e, _ -> tls_error e 78 + | Eof, _ -> return `Eof) 79 + ;; 80 + 81 + let rec read t buf = 82 + let writeout res = 83 + let rlen = String.length res in 84 + let n = min (Bytes.length buf) rlen in 85 + Stdlib.Bytes.blit_string res 0 buf 0 n; 86 + t.linger <- (if n < rlen then Some (Stdlib.String.sub res n (rlen - n)) else None); 87 + return n 88 + in 89 + match t.linger with 90 + | Some res -> writeout res 91 + | None -> 92 + (match%bind read_react t with 93 + | `Eof -> return 0 94 + | `Ok None -> read t buf 95 + | `Ok (Some res) -> writeout res) 96 + ;; 97 + 98 + let writev t css = 99 + match t.state with 100 + | Error err -> tls_error err 101 + | Eof -> tls_error Connection_closed 102 + | Active tls -> 103 + (match Tls.Engine.send_application_data tls css with 104 + | Some (tls, tlsdata) -> 105 + t.state <- Active tls; 106 + Fd.write_full t.fd tlsdata 107 + | None -> tls_error Connection_not_ready) 108 + ;; 109 + 110 + (* 111 + * XXX bad XXX 112 + * This is a point that should particularly be protected from concurrent r/w. 113 + * Doing this before a `t` is returned is safe; redoing it during rekeying is 114 + * not, as the API client already sees the `t` and can mistakenly interleave 115 + * writes while this is in progress. 116 + * *) 117 + let rec drain_handshake t = 118 + let push_linger t mcs = 119 + match mcs, t.linger with 120 + | None, _ -> () 121 + | scs, None -> t.linger <- scs 122 + | Some cs, Some l -> t.linger <- Some (l ^ cs) 123 + in 124 + match t.state with 125 + | Active tls when not (Tls.Engine.handshake_in_progress tls) -> return t 126 + | _ -> 127 + (match%bind read_react t with 128 + | `Eof -> tls_error Unexpected_eof 129 + | `Ok cs -> 130 + push_linger t cs; 131 + drain_handshake t) 132 + ;; 133 + 134 + let reneg ?authenticator ?acceptable_cas ?cert ?(drop = true) t = 135 + match t.state with 136 + | Error err -> tls_error err 137 + | Eof -> tls_error Connection_closed 138 + | Active tls -> 139 + (match Tls.Engine.reneg ?authenticator ?acceptable_cas ?cert tls with 140 + | None -> tls_error Unable_to_renegotiate 141 + | Some (tls', buf) -> 142 + if drop then t.linger <- None; 143 + t.state <- Active tls'; 144 + let%bind () = Fd.write_full t.fd buf in 145 + let%bind _ = drain_handshake t in 146 + return ()) 147 + ;; 148 + 149 + let key_update ?request t = 150 + match t.state with 151 + | Error err -> tls_error err 152 + | Eof -> tls_error Connection_closed 153 + | Active tls -> 154 + (match Tls.Engine.key_update ?request tls with 155 + | Error _ -> tls_error Unable_to_update_key 156 + | Ok (tls', buf) -> 157 + t.state <- Active tls'; 158 + Fd.write_full t.fd buf) 159 + ;; 160 + 161 + let close_tls t = 162 + match t.state with 163 + | Active tls -> 164 + let _, buf = Tls.Engine.send_close_notify tls in 165 + t.state <- Eof; 166 + Fd.write_full t.fd buf 167 + | _ -> return () 168 + ;; 169 + 170 + let server_of_fd config fd = 171 + drain_handshake 172 + { state = Active (Tls.Engine.server config) 173 + ; fd 174 + ; linger = None 175 + ; recv_buf = Bytes.create 4096 176 + } 177 + ;; 178 + 179 + let client_of_fd config ?host fd = 180 + let config' = 181 + match host with 182 + | None -> config 183 + | Some host -> Tls.Config.peer config host 184 + in 185 + let t = { state = Eof; fd; linger = None; recv_buf = Bytes.create 4096 } in 186 + let tls, init = Tls.Engine.client config' in 187 + let t = { t with state = Active tls } in 188 + let%bind () = Fd.write_full t.fd init in 189 + drain_handshake t 190 + ;; 191 + 192 + let epoch t = 193 + match t.state with 194 + | Active tls -> (match Tls.Engine.epoch tls with 195 + | Ok _ as o -> o 196 + | Error () -> Or_error.error_string "no TLS state available yet") 197 + | Eof -> Or_error.error_string "TLS state is end of file" 198 + | Error _ -> Or_error.error_string "TLS state is error" 199 + ;; 200 + end
+6
vendor/opam/tls/async/io.mli
··· 1 + open! Core 2 + 3 + module type Fd = Io_intf.Fd 4 + module type S = Io_intf.S 5 + 6 + module Make (Fd : Fd) : S with module Fd := Fd
+64
vendor/opam/tls/async/io_intf.ml
··· 1 + open! Core 2 + open! Async 3 + 4 + module type Fd = sig 5 + type t 6 + 7 + val read : t -> bytes -> [ `Ok of int | `Eof ] Deferred.Or_error.t 8 + val write_full : t -> string -> unit Deferred.Or_error.t 9 + end 10 + 11 + module type S = sig 12 + module Fd : Fd 13 + 14 + (** Abstract type of a session *) 15 + type t 16 + 17 + (** {2 Constructors} *) 18 + 19 + (** [server_of_fd server fd] is [t], after server-side TLS 20 + handshake of [fd] using [server] configuration. *) 21 + val server_of_fd : Tls.Config.server -> Fd.t -> t Deferred.Or_error.t 22 + 23 + (** [client_of_fd client ~host fd] is [t], after client-side 24 + TLS handshake of [fd] using [client] configuration and [host]. *) 25 + val client_of_fd 26 + : Tls.Config.client 27 + -> ?host:[ `host ] Domain_name.t 28 + -> Fd.t 29 + -> t Deferred.Or_error.t 30 + 31 + (** {2 Common stream operations} *) 32 + 33 + (** [read t buffer] is [length], the number of bytes read into 34 + [buffer]. *) 35 + val read : t -> bytes -> int Deferred.Or_error.t 36 + 37 + (** [writev t buffers] writes the [buffers] to the session. *) 38 + val writev : t -> string list -> unit Deferred.Or_error.t 39 + 40 + (** [close t] closes the TLS session by sending a close notify to the peer. *) 41 + val close_tls : t -> unit Deferred.Or_error.t 42 + 43 + (** [reneg ~authenticator ~acceptable_cas ~cert ~drop t] renegotiates the 44 + session, and blocks until the renegotiation finished. Optionally, a new 45 + [authenticator] and [acceptable_cas] can be used. The own certificate can 46 + be adjusted by [cert]. If [drop] is [true] (the default), 47 + application data received before the renegotiation finished is dropped. *) 48 + val reneg 49 + : ?authenticator:X509.Authenticator.t 50 + -> ?acceptable_cas:X509.Distinguished_name.t list 51 + -> ?cert:Tls.Config.own_cert 52 + -> ?drop:bool 53 + -> t 54 + -> unit Deferred.Or_error.t 55 + 56 + (** [key_update ~request t] updates the traffic key and requests a traffic key 57 + update from the peer if [request] is provided and [true] (the default). 58 + This is only supported in TLS 1.3. *) 59 + val key_update : ?request:bool -> t -> unit Deferred.Or_error.t 60 + 61 + (** [epoch t] returns [epoch], which contains information of the 62 + active session. *) 63 + val epoch : t -> Tls.Core.epoch_data Or_error.t 64 + end
+27
vendor/opam/tls/async/session.ml
··· 1 + open! Core 2 + open! Async 3 + 4 + module Fd = struct 5 + type t = Reader.t * Writer.t 6 + 7 + let read (reader, (_ : Writer.t)) buf = 8 + Deferred.Or_error.try_with (fun () -> Reader.read reader buf) 9 + ;; 10 + 11 + let write ((_ : Reader.t), writer) buf = 12 + Deferred.Or_error.try_with (fun () -> 13 + Writer.write writer buf; 14 + Writer.flushed writer) 15 + ;; 16 + 17 + let rec write_full fd buf = 18 + let open Deferred.Or_error.Let_syntax in 19 + match String.length buf with 20 + | 0 -> return () 21 + | len -> 22 + let%bind () = write fd buf in 23 + write_full fd (String.sub buf ~pos:len ~len:(String.length buf - len)) 24 + ;; 25 + end 26 + 27 + include Io.Make (Fd)
+3
vendor/opam/tls/async/session.mli
··· 1 + open! Core 2 + open! Async 3 + include Io.S with type Fd.t = Reader.t * Writer.t
+154
vendor/opam/tls/async/tls_async.ml
··· 1 + open! Core 2 + open! Async 3 + module Session = Session 4 + module X509_async = X509_async 5 + 6 + let try_to_close t = 7 + match%map Session.close_tls t with 8 + | Ok () -> () 9 + | Error tls_close_error -> Log.Global.error_s [%sexp (tls_close_error : Error.t)] 10 + ;; 11 + 12 + let pipe t = 13 + let b_reader = Bytes.create 0x8000 in 14 + let rec f_reader writer = 15 + match%bind Session.read t b_reader with 16 + | Ok 0 -> 17 + Pipe.close writer; 18 + return () 19 + | Ok len -> 20 + let%bind () = Pipe.write writer (Stdlib.Bytes.sub_string b_reader 0 len) in 21 + f_reader writer 22 + | Error read_error -> 23 + Log.Global.error_s [%sexp (read_error : Error.t)]; 24 + Pipe.close writer; 25 + return () 26 + in 27 + let rec f_writer reader = 28 + let%bind pipe_read = Pipe.read reader in 29 + match pipe_read with 30 + | `Ok s -> 31 + (match%bind Session.writev t [ s ] with 32 + | Ok () -> f_writer reader 33 + | Error (_ : Error.t) -> try_to_close t) 34 + | `Eof -> try_to_close t 35 + in 36 + Pipe.create_reader ~close_on_exception:false f_reader, Pipe.create_writer f_writer 37 + ;; 38 + 39 + let upgrade_connection tls_session ((_ : Reader.t), outer_writer) = 40 + let pipe_r, pipe_w = pipe tls_session in 41 + let%bind inner_reader = Reader.of_pipe (Info.of_string "tls_reader") pipe_r in 42 + let%map inner_writer, `Closed_and_flushed_downstream inner_cafd = 43 + Writer.of_pipe (Info.of_string "tls_writer") pipe_w 44 + in 45 + Writer.set_raise_when_consumer_leaves inner_writer false; 46 + let outer_cafd = 47 + (* Ordering is important here to ensure no data is lost during the session shutdown *) 48 + let%bind () = Writer.close_finished inner_writer in 49 + let%bind () = inner_cafd in 50 + let%bind () = try_to_close tls_session in 51 + Writer.flushed outer_writer 52 + in 53 + tls_session, inner_reader, inner_writer, `Tls_closed_and_flushed_downstream outer_cafd 54 + ;; 55 + 56 + let upgrade_server_reader_writer_to_tls config rw = 57 + let open Deferred.Or_error.Let_syntax in 58 + let%bind tls_session = Session.server_of_fd config rw in 59 + upgrade_connection tls_session rw |> Deferred.ok 60 + ;; 61 + 62 + let upgrade_client_reader_writer_to_tls ?host config rw = 63 + let open Deferred.Or_error.Let_syntax in 64 + let%bind tls_session = Session.client_of_fd ?host config rw in 65 + upgrade_connection tls_session rw |> Deferred.ok 66 + ;; 67 + 68 + type 'a io_handler = Reader.t -> Writer.t -> 'a Deferred.t 69 + type 'a tls_handler = Session.t -> 'a io_handler 70 + 71 + let upgrade_server_handler ~config handle_client outer_reader outer_writer = 72 + let%bind ( tls_session 73 + , inner_reader 74 + , inner_writer 75 + , `Tls_closed_and_flushed_downstream inner_cafd ) 76 + = 77 + upgrade_server_reader_writer_to_tls config (outer_reader, outer_writer) 78 + |> Deferred.Or_error.ok_exn 79 + in 80 + Monitor.protect 81 + (fun () -> handle_client tls_session inner_reader inner_writer) 82 + ~finally:(fun () -> 83 + Deferred.all_unit 84 + [ Reader.close inner_reader; Writer.close inner_writer; inner_cafd ]) 85 + ;; 86 + 87 + let listen 88 + ?buffer_age_limit 89 + ?max_connections 90 + ?max_accepts_per_batch 91 + ?backlog 92 + ?socket 93 + ~on_handler_error 94 + config 95 + where_to_listen 96 + handle_client 97 + = 98 + Tcp.Server.create 99 + ?buffer_age_limit 100 + ?max_connections 101 + ?max_accepts_per_batch 102 + ?backlog 103 + ?socket 104 + ~on_handler_error 105 + where_to_listen 106 + (fun sock -> 107 + upgrade_server_handler ~config (handle_client sock)) 108 + ;; 109 + 110 + let upgrade_client_to_tls config ~host outer_reader outer_writer = 111 + let open Deferred.Or_error.Let_syntax in 112 + let%bind ( tls_session 113 + , inner_reader 114 + , inner_writer 115 + , `Tls_closed_and_flushed_downstream inner_cafd ) 116 + = 117 + upgrade_client_reader_writer_to_tls ?host config (outer_reader, outer_writer) 118 + in 119 + don't_wait_for 120 + (let%bind.Deferred () = inner_cafd in 121 + Deferred.all_unit [ Writer.close outer_writer; Reader.close outer_reader ]); 122 + return (tls_session, inner_reader, inner_writer) 123 + ;; 124 + 125 + let connect 126 + ?socket 127 + ?buffer_age_limit 128 + ?interrupt 129 + ?reader_buffer_size 130 + ?writer_buffer_size 131 + ?timeout 132 + ?time_source 133 + config 134 + where_to_connect 135 + ~host 136 + = 137 + let open Deferred.Or_error.Let_syntax in 138 + let%bind (_ : ([ `Active ], 'a) Socket.t), outer_reader, outer_writer = 139 + Tcp.connect 140 + ?socket 141 + ?buffer_age_limit 142 + ?interrupt 143 + ?reader_buffer_size 144 + ?writer_buffer_size 145 + ?timeout 146 + ?time_source 147 + where_to_connect 148 + |> Deferred.ok 149 + in 150 + upgrade_client_to_tls ~host config outer_reader outer_writer 151 + ;; 152 + 153 + (* initialized RNG early to maximise available entropy. *) 154 + let () = Mirage_crypto_rng_unix.use_default ()
+74
vendor/opam/tls/async/tls_async.mli
··· 1 + open! Core 2 + open! Async 3 + 4 + (** Low-level API for working with TLS sessions. 5 + Most applications should use the high-level API below *) 6 + module Session = Session 7 + 8 + (** Helper functions for [Async_unix]-specific IO operations commonly used with X509 9 + certificates, such as loading from a Unix filesystem *) 10 + module X509_async = X509_async 11 + 12 + (** [listen] creates a [Tcp.Server.t] with the requested parameters, including those 13 + specified in [Tls.Config.server]. The handler function exposes the low-level 14 + [Session.t] to accommodate cases like interrogating a client certificate *) 15 + val listen 16 + : ?buffer_age_limit:Writer.buffer_age_limit 17 + -> ?max_connections:int (** defaults to [10_000]. *) 18 + -> ?max_accepts_per_batch:int (** defaults to [1]. *) 19 + -> ?backlog:int (** defaults to [64]. *) 20 + -> ?socket:([ `Unconnected ], ([< Socket.Address.t ] as 'address)) Socket.t 21 + -> on_handler_error:[ `Call of 'address -> exn -> unit | `Ignore | `Raise ] 22 + -> Tls.Config.server 23 + -> ('address, 'listening_on) Tcp.Where_to_listen.t 24 + -> ('address -> Session.t -> Reader.t -> Writer.t -> unit Deferred.t) 25 + -> ('address, 'listening_on) Tcp.Server.t Deferred.t 26 + 27 + type 'a io_handler = Reader.t -> Writer.t -> 'a Deferred.t 28 + type 'a tls_handler = Session.t -> 'a io_handler 29 + 30 + (** [upgrade_server_handler] is what [listen] calls to handle each client. 31 + It is exposed so that low-level end-users of the library can use tls-async 32 + inside of code that manages Tcp services directly. 33 + 34 + The [tls_handler] argument will be called with the client Tls session, 35 + reader and writer to be used for cleartext data. 36 + 37 + The outer [reader] and [writer] will read encrypted data from and write 38 + encrypted data to the connected socket. *) 39 + val upgrade_server_handler 40 + : config:Tls.Config.server 41 + -> 'a tls_handler 42 + -> 'a io_handler 43 + 44 + (** [connect] behaves similarly to [Tcp.connect], exposing a cleartext reader and writer. 45 + Callers should ensure they close the [Writer.t] and wait for the [unit Deferred.t] 46 + returned by [`Closed_and_flushed_downstream] to completely shut down the TLS connection 47 + 48 + [host] is used for peer name verification and should generally be provided. Passing 49 + [None] will disable peer name verification unless [peer_name] was provided in the 50 + [Tls.Config.client]. If both are present [host] overwrites [peer_name]. 51 + *) 52 + val connect 53 + : ?socket:([ `Unconnected ], 'addr) Socket.t 54 + -> (Tls.Config.client 55 + -> 'addr Tcp.Where_to_connect.t 56 + -> host:[ `host ] Domain_name.t option 57 + -> (Session.t * Reader.t * Writer.t) Deferred.Or_error.t) 58 + Tcp.Aliases.with_connect_options 59 + 60 + (** [upgrade_client_to_tls] upgrades an existing reader/writer to TLS, 61 + returning a cleartext reader and writer. 62 + Callers should ensure they close the [Writer.t] and wait for the [unit Deferred.t] 63 + returned by [`Closed_and_flushed_downstream] to completely shut down the TLS connection 64 + 65 + [host] is used for peer name verification and should generally be provided. Passing 66 + [None] will disable peer name verification unless [peer_name] was provided in the 67 + [Tls.Config.client]. If both are present [host] overwrites [peer_name]. 68 + *) 69 + val upgrade_client_to_tls 70 + : Tls.Config.client 71 + -> host:[ `host ] Domain_name.t option 72 + -> Reader.t 73 + -> Writer.t 74 + -> (Session.t * Reader.t * Writer.t) Deferred.Or_error.t
+271
vendor/opam/tls/async/x509_async.ml
··· 1 + open! Core 2 + open! Async 3 + 4 + let file_contents file = 5 + Deferred.Or_error.try_with ~name:(sprintf "read %s" file) (fun () -> 6 + Reader.file_contents file) 7 + ;; 8 + 9 + let load_all_in_directory ~directory ~f = 10 + let open Deferred.Or_error.Let_syntax in 11 + let%bind files = Deferred.Or_error.try_with (fun () -> Sys.ls_dir directory) in 12 + Deferred.Or_error.List.map ~how:`Sequential files ~f:(fun file -> 13 + let%bind contents = file_contents (directory ^/ file) in 14 + f ~contents) 15 + ;; 16 + 17 + module Or_error = struct 18 + include Or_error 19 + 20 + let of_result ~to_string = Result.map_error ~f:(Fn.compose Error.of_string to_string) 21 + let of_result_msg x = of_result x ~to_string:(fun (`Msg msg) -> msg) 22 + 23 + let lift_result_msg_of_string f ~contents = 24 + f contents |> of_result_msg 25 + ;; 26 + 27 + let lift_asn_error_of_string f ~contents = 28 + f contents |> of_result ~to_string:(fun (`Parse msg) -> msg) 29 + ;; 30 + end 31 + 32 + module CRL = struct 33 + include X509.CRL 34 + 35 + let decode_der = Or_error.lift_result_msg_of_string decode_der 36 + 37 + let revoke ?digest ~issuer ~this_update ?next_update ?extensions revoked_certs key = 38 + revoke ?digest ~issuer ~this_update ?next_update ?extensions revoked_certs key 39 + |> Or_error.of_result_msg 40 + ;; 41 + 42 + let revoke_certificate revoked ~this_update ?next_update crl key = 43 + revoke_certificate revoked ~this_update ?next_update crl key |> Or_error.of_result_msg 44 + ;; 45 + 46 + let revoke_certificates revoked ~this_update ?next_update crl key = 47 + revoke_certificates revoked ~this_update ?next_update crl key 48 + |> Or_error.of_result_msg 49 + ;; 50 + 51 + let of_pem_dir ~directory = 52 + load_all_in_directory ~directory ~f:(fun ~contents -> 53 + decode_der ~contents |> Deferred.return) 54 + ;; 55 + end 56 + 57 + module Certificate = struct 58 + include X509.Certificate 59 + open Deferred.Or_error.Let_syntax 60 + 61 + let decode_pem_multiple = Or_error.lift_result_msg_of_string decode_pem_multiple 62 + let decode_pem = Or_error.lift_result_msg_of_string decode_pem 63 + let decode_der = Or_error.lift_result_msg_of_string decode_der 64 + 65 + let of_pem_file ca_file = 66 + let%bind contents = file_contents ca_file in 67 + decode_pem_multiple ~contents |> Deferred.return 68 + ;; 69 + 70 + let of_pem_directory ~directory = 71 + load_all_in_directory ~directory ~f:(fun ~contents -> 72 + decode_pem_multiple ~contents |> Deferred.return) 73 + >>| List.concat 74 + ;; 75 + end 76 + 77 + module Authenticator = struct 78 + include X509.Authenticator 79 + 80 + module Param = struct 81 + module Chain_of_trust = struct 82 + type t = 83 + { trust_anchors : [ `File of Filename.t | `Directory of Filename.t ] 84 + ; allowed_hashes : Digestif.hash' list option 85 + ; crls : Filename.t option 86 + } 87 + 88 + let to_certs = function 89 + | `File file -> Certificate.of_pem_file file 90 + | `Directory directory -> Certificate.of_pem_directory ~directory 91 + ;; 92 + end 93 + 94 + type t = 95 + | Chain_of_trust of Chain_of_trust.t 96 + | Cert_fingerprint of Digestif.hash' * string 97 + | Key_fingerprint of Digestif.hash' * string 98 + 99 + let ca_file ?allowed_hashes ?crls filename () = 100 + let trust_anchors = `File filename in 101 + Chain_of_trust { trust_anchors; allowed_hashes; crls } 102 + ;; 103 + 104 + let ca_dir ?allowed_hashes ?crls directory_name () = 105 + let trust_anchors = `Directory directory_name in 106 + Chain_of_trust { trust_anchors; allowed_hashes; crls } 107 + ;; 108 + 109 + let cert_fingerprint hash fingerprint = Cert_fingerprint (hash, fingerprint) 110 + 111 + let key_fingerprint hash fingerprint = Key_fingerprint (hash, fingerprint) 112 + 113 + let cleanup_fingerprint fingerprint = 114 + let known_delimiters = [ ':'; ' ' ] in 115 + String.filter fingerprint ~f:(fun c -> 116 + not (List.exists known_delimiters ~f:(Char.equal c))) 117 + |> Ohex.decode 118 + ;; 119 + 120 + let of_cas ~time ({ trust_anchors; allowed_hashes; crls } : Chain_of_trust.t) = 121 + let open Deferred.Or_error.Let_syntax in 122 + let%bind cas = Chain_of_trust.to_certs trust_anchors in 123 + let%map crls = 124 + match crls with 125 + | Some directory -> 126 + let%map crls = CRL.of_pem_dir ~directory in 127 + Some crls 128 + | None -> return None 129 + in 130 + X509.Authenticator.chain_of_trust ?allowed_hashes ?crls ~time cas 131 + ;; 132 + 133 + let of_cert_fingerprint ~time hash fingerprint = 134 + let fingerprint = cleanup_fingerprint fingerprint in 135 + X509.Authenticator.cert_fingerprint ~time ~hash ~fingerprint 136 + ;; 137 + 138 + let of_key_fingerprint ~time hash fingerprint = 139 + let fingerprint = cleanup_fingerprint fingerprint in 140 + X509.Authenticator.key_fingerprint ~time ~hash ~fingerprint 141 + ;; 142 + 143 + let time = Fn.compose Ptime.of_float_s Unix.gettimeofday 144 + 145 + let to_authenticator ~time param = 146 + match param with 147 + | Chain_of_trust chain_of_trust -> of_cas ~time chain_of_trust 148 + | Cert_fingerprint (hash, fingerprint) -> 149 + of_cert_fingerprint ~time hash fingerprint |> Deferred.Or_error.return 150 + | Key_fingerprint (hash, fingerprint) -> 151 + of_key_fingerprint ~time hash fingerprint |> Deferred.Or_error.return 152 + ;; 153 + end 154 + end 155 + 156 + module Distinguished_name = struct 157 + include X509.Distinguished_name 158 + 159 + let decode_der = Or_error.lift_result_msg_of_string decode_der 160 + end 161 + 162 + module OCSP = struct 163 + include X509.OCSP 164 + 165 + module Request = struct 166 + include Request 167 + 168 + let create ?certs ?digest ?requestor_name ?key cert_ids = 169 + create ?certs ?digest ?requestor_name ?key cert_ids |> Or_error.of_result_msg 170 + ;; 171 + 172 + let decode_der = Or_error.lift_asn_error_of_string decode_der 173 + end 174 + 175 + module Response = struct 176 + include Response 177 + 178 + let create_success 179 + ?digest 180 + ?certs 181 + ?response_extensions 182 + private_key 183 + responderID 184 + producedAt 185 + responses 186 + = 187 + create_success 188 + ?digest 189 + ?certs 190 + ?response_extensions 191 + private_key 192 + responderID 193 + producedAt 194 + responses 195 + |> Or_error.of_result_msg 196 + ;; 197 + 198 + let responses t = responses t |> Or_error.of_result_msg 199 + let decode_der = Or_error.lift_asn_error_of_string decode_der 200 + end 201 + end 202 + 203 + module PKCS12 = struct 204 + include X509.PKCS12 205 + 206 + let decode_der = Or_error.lift_result_msg_of_string decode_der 207 + let verify password t = verify password t |> Or_error.of_result_msg 208 + end 209 + 210 + module Private_key = struct 211 + include X509.Private_key 212 + 213 + let sign hash ?scheme key data = 214 + sign hash ?scheme key data 215 + |> Or_error.of_result_msg 216 + ;; 217 + 218 + let decode_der = Or_error.lift_result_msg_of_string decode_der 219 + let decode_pem = Or_error.lift_result_msg_of_string decode_pem 220 + 221 + let of_pem_file file = 222 + let%map contents = Reader.file_contents file in 223 + decode_pem ~contents 224 + ;; 225 + end 226 + 227 + module Public_key = struct 228 + include X509.Public_key 229 + 230 + let verify hash ?scheme ~signature key data = 231 + verify hash ?scheme ~signature key data |> Or_error.of_result_msg 232 + ;; 233 + 234 + let decode_der = Or_error.lift_result_msg_of_string decode_der 235 + let decode_pem = Or_error.lift_result_msg_of_string decode_pem 236 + end 237 + 238 + module Signing_request = struct 239 + include X509.Signing_request 240 + 241 + let decode_der ?allowed_hashes der = 242 + decode_der ?allowed_hashes der |> Or_error.of_result_msg 243 + ;; 244 + 245 + let decode_pem pem = decode_pem pem |> Or_error.of_result_msg 246 + 247 + let create subject ?digest ?extensions key = 248 + create subject ?digest ?extensions key |> Or_error.of_result_msg 249 + ;; 250 + 251 + let sign 252 + ?allowed_hashes 253 + ?digest 254 + ?serial 255 + ?extensions 256 + t 257 + key 258 + issuer 259 + ~valid_from 260 + ~valid_until 261 + = 262 + sign ?allowed_hashes ?digest ?serial ?extensions t key issuer ~valid_from ~valid_until 263 + |> Or_error.of_result ~to_string:(Fmt.to_to_string X509.Validation.pp_signature_error) 264 + ;; 265 + end 266 + 267 + module Extension = X509.Extension 268 + module General_name = X509.General_name 269 + module Host = X509.Host 270 + module Key_type = X509.Key_type 271 + module Validation = X509.Validation
+231
vendor/opam/tls/async/x509_async.mli
··· 1 + open! Core 2 + open! Async 3 + 4 + include module type of struct 5 + include X509 6 + end 7 + 8 + module Authenticator : sig 9 + include module type of struct 10 + include Authenticator 11 + end 12 + 13 + module Param : sig 14 + type t 15 + 16 + val ca_file 17 + : ?allowed_hashes:Digestif.hash' list 18 + -> ?crls:Filename.t 19 + -> Filename.t 20 + -> unit 21 + -> t 22 + 23 + val ca_dir 24 + : ?allowed_hashes:Digestif.hash' list 25 + -> ?crls:Filename.t 26 + -> Filename.t 27 + -> unit 28 + -> t 29 + 30 + (** The fingerprint can be collected from a browser or by invoking an openssl command 31 + like 'openssl x509 -in <pem_file> -noout -fingerprint -sha256' *) 32 + val cert_fingerprint 33 + : Digestif.hash' 34 + -> string 35 + -> t 36 + 37 + (** The fingerprint can be collected from a browser or by invoking an openssl command 38 + like 'openssl x509 -in <pem_file> -noout -pubkey | openssl pkey -pubin -outform DER | openssl dgst -sha256' *) 39 + val key_fingerprint 40 + : Digestif.hash' 41 + -> string 42 + -> t 43 + 44 + (** Async programs often don't use [Ptime_clock], so this is provided as a convenience 45 + function. Relies on [Unix.gettimeofday]. *) 46 + val time : unit -> Ptime.t option 47 + 48 + val to_authenticator 49 + : time:(unit -> Ptime.t option) 50 + -> t 51 + -> Authenticator.t Deferred.Or_error.t 52 + end 53 + end 54 + 55 + module Private_key : sig 56 + include module type of struct 57 + include Private_key 58 + end 59 + 60 + val sign 61 + : Digestif.hash' 62 + -> ?scheme:Key_type.signature_scheme 63 + -> t 64 + -> [ `Digest of string | `Message of string ] 65 + -> string Or_error.t 66 + 67 + val decode_der : contents:string -> t Or_error.t 68 + val decode_pem : contents:string -> t Or_error.t 69 + val of_pem_file : Filename.t -> t Deferred.Or_error.t 70 + end 71 + 72 + module Public_key : sig 73 + include module type of struct 74 + include Public_key 75 + end 76 + 77 + val verify 78 + : Digestif.hash' 79 + -> ?scheme:Key_type.signature_scheme 80 + -> signature:string 81 + -> t 82 + -> [ `Digest of string | `Message of string ] 83 + -> unit Or_error.t 84 + 85 + val decode_der : contents:string -> t Or_error.t 86 + val decode_pem : contents:string -> t Or_error.t 87 + end 88 + 89 + module Certificate : sig 90 + include module type of struct 91 + include Certificate 92 + end 93 + 94 + val decode_pem_multiple : contents:string -> t list Or_error.t 95 + val decode_pem : contents:string -> t Or_error.t 96 + val decode_der : contents:string -> t Or_error.t 97 + val of_pem_file : Filename.t -> t list Deferred.Or_error.t 98 + val of_pem_directory : directory:Filename.t -> t list Deferred.Or_error.t 99 + end 100 + 101 + module Distinguished_name : sig 102 + include module type of struct 103 + include Distinguished_name 104 + end 105 + 106 + val decode_der : contents:string -> t Or_error.t 107 + end 108 + 109 + module CRL : sig 110 + include module type of struct 111 + include CRL 112 + end 113 + 114 + val decode_der : contents:string -> t Or_error.t 115 + 116 + val revoke 117 + : ?digest:Digestif.hash' 118 + -> issuer:Distinguished_name.t 119 + -> this_update:Ptime.t 120 + -> ?next_update:Ptime.t 121 + -> ?extensions:Extension.t 122 + -> revoked_cert list 123 + -> Private_key.t 124 + -> t Or_error.t 125 + 126 + val revoke_certificate 127 + : revoked_cert 128 + -> this_update:Ptime.t 129 + -> ?next_update:Ptime.t 130 + -> t 131 + -> Private_key.t 132 + -> t Or_error.t 133 + 134 + val revoke_certificates 135 + : revoked_cert list 136 + -> this_update:Ptime.t 137 + -> ?next_update:Ptime.t 138 + -> t 139 + -> Private_key.t 140 + -> t Or_error.t 141 + 142 + val of_pem_dir : directory:Filename.t -> t list Deferred.Or_error.t 143 + end 144 + 145 + module OCSP : sig 146 + include module type of struct 147 + include OCSP 148 + end 149 + 150 + module Request : sig 151 + include module type of struct 152 + include Request 153 + end 154 + 155 + val create 156 + : ?certs:Certificate.t list 157 + -> ?digest:Digestif.hash' 158 + -> ?requestor_name:General_name.b 159 + -> ?key:Private_key.t 160 + -> cert_id list 161 + -> t Or_error.t 162 + 163 + val decode_der : contents:string -> t Or_error.t 164 + end 165 + 166 + module Response : sig 167 + include module type of struct 168 + include Response 169 + end 170 + 171 + val create_success 172 + : ?digest:Digestif.hash' 173 + -> ?certs:Certificate.t list 174 + -> ?response_extensions:Extension.t 175 + -> Private_key.t 176 + -> responder_id 177 + -> Ptime.t 178 + -> single_response list 179 + -> t Or_error.t 180 + 181 + val responses : t -> single_response list Or_error.t 182 + val decode_der : contents:string -> t Or_error.t 183 + end 184 + end 185 + 186 + module PKCS12 : sig 187 + include module type of struct 188 + include PKCS12 189 + end 190 + 191 + val decode_der : contents:string -> t Or_error.t 192 + 193 + val verify 194 + : string 195 + -> t 196 + -> [ `Certificate of Certificate.t 197 + | `Crl of CRL.t 198 + | `Decrypted_private_key of Private_key.t 199 + | `Private_key of Private_key.t 200 + ] 201 + list 202 + Or_error.t 203 + end 204 + 205 + module Signing_request : sig 206 + include module type of struct 207 + include Signing_request 208 + end 209 + 210 + val decode_der : ?allowed_hashes:Digestif.hash' list -> string -> t Or_error.t 211 + val decode_pem : string -> t Or_error.t 212 + 213 + val create 214 + : Distinguished_name.t 215 + -> ?digest:Digestif.hash' 216 + -> ?extensions:Ext.t 217 + -> Private_key.t 218 + -> t Or_error.t 219 + 220 + val sign 221 + : ?allowed_hashes:Digestif.hash' list 222 + -> ?digest:Digestif.hash' 223 + -> ?serial:string 224 + -> ?extensions:Extension.t 225 + -> t 226 + -> Private_key.t 227 + -> Distinguished_name.t 228 + -> valid_from:Ptime.t 229 + -> valid_until:Ptime.t 230 + -> Certificate.t Or_error.t 231 + end
+293
vendor/opam/tls/attacks.md
··· 1 + ### Attacks on TLS 2 + 3 + TLS the most widely deployed security protocol on the Internet and, at 4 + over 15 years, is also showing its age. As such, a flaw is a valuable 5 + commodity due to the commercially sensitive nature of data that is 6 + encrypted with TLS. Various vulnerabilities on different layers of TLS 7 + have been found - [heartbleed][] and others are implementation 8 + specific, advancements in cryptanalysis such as [collisions of 9 + MD5][md5_collision] lead to vulnerabilities, and even others are due 10 + to incorrect usage of TLS ([truncation attack][truncation] or 11 + [BREACH][breach]). Finally, some weaknesses are in the protocol 12 + itself. Extensive [overviews][tls_attacks] of [attacks on 13 + TLS][mitls_attacks] are available. 14 + 15 + We look at protocol level attacks of TLS and how [ocaml-tls][ocaml-tls] 16 + implements mitigations against these. [TLS 1.2 RFC][RFC5246] provides an 17 + overview of attacks and mitigations, and we [track][issue31] our progress in 18 + covering them. This is slightly out of date as the RFC is roughly six years old and 19 + in the meantime more attacks have been published, such as the [renegotiation 20 + flaw][understanding_reneg]. 21 + 22 + We track all our [mitigated][closed] and [open][open] security issues 23 + on our GitHub issue tracker. 24 + 25 + Due to the choice of using OCaml, a memory managed programming 26 + language, we obstruct entire bug classes, namely temporal and spatial 27 + memory safety. 28 + 29 + Cryptanalysis and improvement of computational power weaken some 30 + ciphers, such as RC4 and 3DES (see [issue 8][issue8] and [issue 31 + 10][issue10]). If we phase these two ciphers out, there wouldn't be 32 + any matching ciphersuite left to communicate with some compliant TLS-1.0 33 + implementations, such as Windows XP, that do not support AES. 34 + 35 + [issue8]: https://github.com/mirleft/ocaml-tls/issues/8 36 + [issue10]: https://github.com/mirleft/ocaml-tls/issues/10 37 + [open]: https://github.com/mirleft/ocaml-tls/issues?labels=security+concern&page=1&state=open 38 + [closed]: https://github.com/mirleft/ocaml-tls/issues?labels=security+concern&page=1&state=closed 39 + [ocaml-tls]: https://github.com/mirleft/ocaml-tls 40 + [understanding_reneg]: http://www.educatedguesswork.org/2009/11/understanding_the_tls_renegoti.html 41 + [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed 42 + [md5_collision]: http://eprint.iacr.org/2005/067 43 + [truncation]: http://www.theregister.co.uk/2013/08/01/gmail_hotmail_hijacking/ 44 + [breach]: http://breachattack.com/ 45 + [RFC5246]: https://tools.ietf.org/html/rfc5246#appendix-D.4 46 + [tls_attacks]: http://eprint.iacr.org/2013/049.pdf 47 + [mitls_attacks]: http://www.mitls.org/wsgi/tls-attacks 48 + [issue31]: https://github.com/mirleft/ocaml-tls/issues/31 49 + 50 + **Timing attacks** 51 + 52 + When the timing characteristics between the common case and the error 53 + case are different, this might potentially leak confidential 54 + information. Timing is a very prominent side-channel and there are a huge 55 + variety of timing attacks on different layers, which are observable by 56 + different attackers. Small differences in timing behaviour might 57 + initially be exploitable only by a local attacker, but advancements to 58 + the attack (e.g. increasing the number of tests) might allow a 59 + remote attacker to filter the noise and exploit the different timing 60 + behaviour. 61 + 62 + **Timing of cryptographic primitives** 63 + 64 + We [already mentioned][nocrypto-intro] [cache][] [timing][cache_timing] 65 + attacks on our AES implementation, and that we use [blinding][] 66 + techniques to mitigate RSA timing attacks. 67 + 68 + By using a memory managed programming language, we open the attack 69 + vector of garbage collector (GC) timing attacks (also mentioned [in 70 + our nocrypto introduction][nocrypto-intro]). 71 + 72 + Furthermore, research has been done on virtual machine side channels 73 + ([l3][], [cross vm][cross_vm] and [cache timing][cache_vm]), which we 74 + will need to study and mitigate appropriately. 75 + 76 + **For the time being we suggest to not use the stack on a multi-tenant 77 + shared host or on a shared host which malicious users might have 78 + access to.** 79 + 80 + [blinding]: https://en.wikipedia.org/wiki/Blinding_(cryptography) 81 + [cache]: http://www.cs.tau.ac.il/~tromer/papers/cache.pdf 82 + [cache_timing]: http://cr.yp.to/antiforgery/cachetiming-20050414.pdf 83 + [l3]: http://eprint.iacr.org/2013/448.pdf 84 + [cross_vm]: http://www.cs.unc.edu/~reiter/papers/2012/CCS.pdf 85 + [cache_vm]: http://fc12.ifca.ai/pre-proceedings/paper_70.pdf 86 + 87 + **Bleichenbacher** 88 + 89 + In 1998, Daniel Bleichenbacher discovered a [timing flaw in the 90 + PKCS1][bleichenbacher] encoding of the premaster secret: the TLS server 91 + failed faster when the padding was wrong than when the decryption 92 + failed. Using this timing, an attacker can run an adaptive chosen 93 + ciphertext attack and find out the plain text of a PKCS1 encrypted 94 + message. In TLS, when RSA is used as the key exchange method, this 95 + leads to discovery of the premaster secret, which is used to derive the 96 + keys for the current session. 97 + 98 + The mitigation is to have both padding and decryption failures use the 99 + exact same amount of time, thus there should not be any data-dependent 100 + branches or different memory access patterns in the code. We 101 + implemented this mitigation in [Handshake_server][answer_client_key_exchange]. 102 + 103 + [bleichenbacher]: http://archiv.infsec.ethz.ch/education/fs08/secsem/Bleichenbacher98.pdf 104 + [answer_client_key_exchange]: https://github.com/mirleft/ocaml-tls/blob/c06cbaaffe49024d8570916b70f7839603a54692/lib/handshake_server.ml#L45 105 + 106 + **Padding oracle and CBC timing** 107 + 108 + [Vaudenay][] discovered a vulnerability involving block ciphers: if an 109 + attacker can distinguish between bad mac and bad padding, recovery of 110 + the plaintext is possible (within an adaptive chosen ciphertext 111 + attack). Another approach using the same issue is to use 112 + [timing][practical] information instead of separate error messages. 113 + Further details are described [here][tls_cbc]. 114 + 115 + The countermeasure, which we implement [here][cbc_mit], is to continue 116 + with the mac computation even though the padding is 117 + incorrect. Furthermore, we send the same alert (`bad_record_mac`) 118 + independent of whether the padding is malformed or the mac is 119 + incorrect. 120 + 121 + [tls_cbc]: https://www.openssl.org/~bodo/tls-cbc.txt 122 + [Vaudenay]: http://www.iacr.org/archive/eurocrypt2002/23320530/cbc02_e02d.pdf 123 + [practical]: http://lasecwww.epfl.ch/memo/memo_ssl.shtml 124 + [cbc_mit]: https://github.com/mirleft/ocaml-tls/blob/c06cbaaffe49024d8570916b70f7839603a54692/lib/engine.ml#L100 125 + 126 + **Lucky 13** 127 + 128 + An advancement of the CBC timing attack was discovered in 2013, named 129 + [Lucky 13][Lucky13]. Due to the fact that the mac is computed over the 130 + plaintext without padding, there is a slight (but measurable) 131 + difference in timing between computing the mac of the plaintext and 132 + computing the fake mac of the ciphertext. This leaks information. We 133 + do not have proper mitigation against Lucky 13 in place yet. You can 134 + find further discussion in [issue 7][issue7] and [pull request 135 + 49][pull49]. 136 + 137 + [Lucky13]: http://www.isg.rhul.ac.uk/tls/Lucky13.html 138 + [issue7]: https://github.com/mirleft/ocaml-tls/issues/7 139 + [pull49]: https://github.com/mirleft/ocaml-tls/pull/49 140 + 141 + **Renegotiation not authenticated** 142 + 143 + In 2009, Marsh Ray published a vulnerability of the TLS protocol which 144 + lets an attacker prepend arbitrary data to a session due to 145 + [unauthenticated renegotiation][understanding_reneg]. The attack 146 + exploits the fact that a renegotiation of ciphers and key material is 147 + possible within a session, and this renegotiated handshake is not 148 + authenticated by the previous handshake. A man in the middle can 149 + initiate a session with a server, send some data, and hand over the 150 + session to a client. Neither the client nor the server can detect the 151 + man in the middle. 152 + 153 + A fix for this issue is the [secure renegotiation extension][RFC5746], 154 + which embeds authenticated data of the previous handshake into the 155 + client and server hello messages. Now, if a man in the middle 156 + initiates a renegotiation, the server will not complete it due to 157 + missing authentication data (the client believes this is the first 158 + handshake). 159 + 160 + We implement and require the secure renegotiation extension by 161 + default, but it is possible to configure `ocaml-tls` to not require 162 + it -- to be able to communicate with servers and 163 + clients which do not support this extension. 164 + 165 + Implementation of the mitigation is on the server side in 166 + [ensure_reneg][] and on the client side in [validate_reneg][]. The 167 + data required for the secure renegotiation is stored in 168 + [`handshake_state`][reneg_state] while sending and receiving Finished 169 + messages. You can find further discussion in [issue 3][issue3]. 170 + 171 + [RFC5746]: https://tools.ietf.org/html/rfc5746 172 + [validate_reneg]: https://github.com/mirleft/ocaml-tls/blob/c06cbaaffe49024d8570916b70f7839603a54692/lib/handshake_client.ml#L50 173 + [ensure_reneg]: https://github.com/mirleft/ocaml-tls/blob/c06cbaaffe49024d8570916b70f7839603a54692/lib/handshake_server.ml#L85 174 + [issue3]: https://github.com/mirleft/ocaml-tls/issues/3 175 + [reneg_state]: https://github.com/mirleft/ocaml-tls/blob/c06cbaaffe49024d8570916b70f7839603a54692/lib/state.ml#L97 176 + 177 + **TLS 1.0 and known-plaintext (BEAST)** 178 + 179 + TLS 1.0 reuses the last ciphertext block as IV in CBC mode. If an attacker 180 + has a (partially) known plaintext, she can find the remaining plaintext. 181 + This is known as the [BEAST][] attack and there is a [long discussion][mozilla-bug] 182 + about mitigations. Our mitigation is to prepend each TLS-1.0 183 + application data fragment with an empty fragment to randomize the IV. 184 + We do this exactly [here][empty_iv]. There is further discussion in 185 + [issue 2][issue2]. 186 + 187 + Our mitigation is slightly different from the 1/n-1 splitting proposed 188 + [here][qualys]: we split every application data frame into a 0 byte 189 + and n byte frame, whereas they split into a 1 byte and a n-1 byte 190 + frame. 191 + 192 + Researchers have exploited this vulnerability in 2011, although it was 193 + known since [2006][]. TLS versions 1.1 and 1.2 use an explicit IV, 194 + instead of reusing the last cipher block on the wire. 195 + 196 + [qualys]: https://community.qualys.com/blogs/securitylabs/2013/09/10/is-beast-still-a-threat 197 + [mozilla-bug]: https://bugzilla.mozilla.org/show_bug.cgi?id=665814 198 + [BEAST]: http://vnhacker.blogspot.co.uk/2011/09/beast.html 199 + [empty_iv]: https://github.com/mirleft/ocaml-tls/blob/c06cbaaffe49024d8570916b70f7839603a54692/lib/engine.ml#L375 200 + [2006]: http://eprint.iacr.org/2006/136 201 + [issue2]: https://github.com/mirleft/ocaml-tls/issues/2 202 + 203 + **Compression and information leakage (CRIME)** 204 + 205 + When using compression on a chosen-plaintext, encrypting this can leak 206 + information, known as [CRIME][crime]. [BREACH][breach] furthermore 207 + exploits application layer compression, such as HTTP compression. We 208 + mitigate CRIME by not providing any TLS compression support, while we 209 + cannot do anything to mitigate BREACH. 210 + 211 + [crime]: http://arstechnica.com/security/2012/09/crime-hijacks-https-sessions/ 212 + 213 + **Traffic analysis** 214 + 215 + Due to limited amount of padding data, the actual size of transmitted 216 + data can be recovered. The mitigation is to implement [length hiding 217 + policies][length_hiding]. This is tracked as [issue 162][issue162]. 218 + 219 + [issue162]: https://github.com/mirleft/ocaml-tls/issues/162 220 + [length_hiding]: http://tools.ietf.org/html/draft-pironti-tls-length-hiding-02 221 + 222 + **Version rollback** 223 + 224 + SSL-2.0 is insecure, a man in the middle can downgrade the version to 225 + SSL-2.0. The mitigation we implement is that we do not support 226 + SSL-2.0, and thus cannot be downgraded. Also, we check that the 227 + version of the client hello matches the first two bytes in the 228 + premaster secret [here][client_version]. You can find further discussion in 229 + [issue 5][issue5]. 230 + 231 + [client_version]: https://github.com/mirleft/ocaml-tls/blob/c06cbaaffe49024d8570916b70f7839603a54692/lib/handshake_server.ml#L55 232 + [issue5]: https://github.com/mirleft/ocaml-tls/issues/5 233 + 234 + **Triple handshake** 235 + 236 + A vulnerability including session resumption and renegotiation was 237 + discovered by the [miTLS team][mitls], named [triple 238 + handshake][triple]. Mitigations include disallowing renegotiation, 239 + disallowing modification of the certificate during renegotiation, or 240 + a hello extension. Since we do not support session resumption yet, we 241 + have not yet implemented any of the mentioned mitigations. There is 242 + further discussion in [issue 9][issue9]. 243 + 244 + [mitls]: http://www.mitls.org 245 + [issue9]: https://github.com/mirleft/ocaml-tls/issues/9 246 + [triple]: https://secure-resumption.com/ 247 + 248 + **Alert attack** 249 + 250 + A [fragment of an alert][alert_attack] can be sent by a man in the 251 + middle during the initial handshake. If the fragment is not cleared 252 + once the handshake is finished, the authentication of alerts is 253 + broken. This was discovered in 2012; our mitigation is to discard 254 + fragmented alerts. 255 + 256 + [alert_attack]: http://www.mitls.org/wsgi/alert-attack 257 + 258 + ### EOF. 259 + 260 + Within six months, two hackers managed to develop a clean-slate TLS 261 + stack, together with required crypto primitives, ASN.1, and X.509 262 + handling, in a high-level pure language. We interoperate with widely 263 + deployed TLS stacks, as shown by our [demo server][demo]. The code 264 + size is nearly two orders of magnitude smaller than OpenSSL, the most 265 + widely used open source library (written in C, which a lot of 266 + programming languages wrap instead of providing their own TLS 267 + implementation). Our code base seems to be robust -- the [demo 268 + server][demo] successfully finished over 22500 sessions in less than a 269 + week, with only 11 failing traces. 270 + 271 + There is a huge need for high quality TLS implementations, because 272 + several TLS implementations suffered this year from severe security 273 + problems, such as [heartbleed][], [goto fail][CVE-2014-1266], [session 274 + id][CVE-2014-3466], [Bleichenbacher][java], [change cipher 275 + suite][CVE-2014-0224] and [GCM DoS][polar]. The main cause is 276 + implementation complexity due to lack of abstraction, and memory 277 + safety issues. 278 + 279 + We still need to address some security issues, and improve our performance. We 280 + invite people to do rigorous code audits (both manual and automated) and try 281 + testing our code in their services. 282 + 283 + **Please be aware that this release is a *beta* and is missing external code audits. 284 + It is not yet intended for use in any security critical applications.** 285 + 286 + [demo]: https://tls.openmirage.org 287 + [polar]: https://polarssl.org/tech-updates/security-advisories/polarssl-security-advisory-2014-02 288 + [java]: http://armoredbarista.blogspot.de/2014/04/easter-hack-even-more-critical-bugs-in.html 289 + [CVE-2014-1266]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-1266 290 + [CVE-2014-3466]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3466 291 + [CVE-2014-0224]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0224 292 + 293 + [nocrypto-intro]: http://openmirage.org/blog/introducing-nocrypto
+3
vendor/opam/tls/bench/dune
··· 1 + (executable 2 + (name speed) 3 + (libraries fmt.tty logs.fmt mirage-crypto-rng mirage-crypto-rng.unix tls ptime.clock.os))
+284
vendor/opam/tls/bench/speed.ml
··· 1 + let now = Ptime_clock.now 2 + 3 + let cert ~digest ~key = 4 + let subject = 5 + let open X509.Distinguished_name in 6 + [ Relative_distinguished_name.singleton (CN "ocaml-tls") ] 7 + in 8 + let csr = X509.Signing_request.create ~digest subject key |> Result.get_ok in 9 + let pubkey = (X509.Signing_request.info csr).public_key in 10 + let extensions = 11 + let open X509.Extension in 12 + let auth = 13 + (Some (X509.Public_key.id pubkey), X509.General_name.empty, None) 14 + in 15 + singleton Authority_key_id (false, auth) 16 + |> add Subject_key_id (false, X509.Public_key.id pubkey) 17 + |> add Basic_constraints (true, (true, None)) 18 + |> add Key_usage 19 + (true, 20 + [ `Key_cert_sign 21 + ; `CRL_sign 22 + ; `Digital_signature 23 + ; `Content_commitment 24 + ; `Key_encipherment ]) 25 + |> add Ext_key_usage (true, [ `Server_auth ]) 26 + in 27 + let valid_from = now () in 28 + let valid_until = Ptime.add_span valid_from (Ptime.Span.of_int_s 60) in 29 + let valid_until = Option.get valid_until in 30 + let cert = X509.Signing_request.sign csr ~valid_from ~valid_until ~digest 31 + ~extensions key subject in 32 + match cert with 33 + | Ok cert -> cert 34 + | Error e -> Fmt.failwith "cert error %a" X509.Validation.pp_signature_error e 35 + 36 + let authenticator ?ip:_ ~host:_ _certs = Ok None 37 + 38 + let consume state input = 39 + match Tls.Engine.handle_tls state input with 40 + | Ok (state, Some `Eof, `Response out, `Data v) -> 41 + let data = Option.fold ~none:0 ~some:String.length v in 42 + `Eof state, out, data 43 + | Ok (state, None, `Response out, `Data v) -> 44 + let data = Option.fold ~none:0 ~some:String.length v in 45 + `Continue state, out, data 46 + | Error (err, `Response out) -> 47 + `Error err, Some out, 0 48 + 49 + let to_state state input = 50 + match consume state input with 51 + | `Eof _, _, _ -> Fmt.failwith "Unexpected eof" 52 + | `Error err, _, _ -> Fmt.failwith "Unexpected error: %a" Tls.Engine.pp_failure err 53 + | `Continue state, out, data -> state, out, data 54 + 55 + type flow = 56 + | To_client of Tls.Engine.state * Tls.Engine.state * string option 57 + | To_server of Tls.Engine.state * Tls.Engine.state * string option 58 + 59 + type state = 60 + { flow : flow 61 + ; server_out : int 62 + ; client_out : int 63 + ; direction : [ `To_server | `To_client ] } 64 + 65 + let get_ok = function 66 + | Ok cfg -> cfg 67 + | Error `Msg msg -> invalid_arg msg 68 + 69 + let make ?groups ~cipher ~digest ~key version direction = 70 + let cert = cert ~digest ~key in 71 + let client_cfg = 72 + get_ok (Tls.Config.client ?groups ~version:(version, version) 73 + ~ciphers:[ cipher ] ~authenticator ()) 74 + and server_cfg = 75 + get_ok (Tls.Config.server ~certificates:(`Single ([ cert ], key)) ()) 76 + in 77 + let client_state, client_out = Tls.Engine.client client_cfg 78 + and server_state = Tls.Engine.server server_cfg in 79 + { flow= To_server (client_state, server_state, Some client_out) 80 + ; server_out= 0 81 + ; client_out= 0 82 + ; direction } 83 + 84 + let actually_send_application_data client_state server_state direction buf = 85 + match direction with 86 + | `To_server -> 87 + let[@warning "-8"] Some (client_state, to_server) = 88 + Tls.Engine.send_application_data client_state [ buf ] in 89 + To_server (client_state, server_state, Some to_server) 90 + | `To_client -> 91 + let[@warning "-8"] Some (server_state, to_client) = 92 + Tls.Engine.send_application_data server_state [ buf ] in 93 + To_client (client_state, server_state, Some to_client) 94 + 95 + let rec once state buf = match state.flow, buf with 96 + | To_server (client_state, server_state, None), Some buf 97 + | To_client (client_state, server_state, None), Some buf -> 98 + let flow = actually_send_application_data 99 + client_state server_state state.direction buf in 100 + once { state with flow } None 101 + | To_server (_, _, None), None 102 + | To_client (_, _, None), None -> state 103 + | To_server (client_state, server_state, Some to_server), buf -> 104 + let server_state, to_client, n = to_state server_state to_server in 105 + let flow = To_client (client_state, server_state, to_client) in 106 + once { state with flow; server_out= state.server_out + n } buf 107 + | To_client (client_state, server_state, Some to_client), _ -> 108 + let client_state, to_server, n = to_state client_state to_client in 109 + let flow = To_server (client_state, server_state, to_server) in 110 + once { state with flow; client_out= state.client_out + n } buf 111 + 112 + let to_consumer state = 113 + let state = ref state in 114 + fun buf -> state := once !state (Some buf) 115 + 116 + module Time = struct 117 + let time ~n fn a = 118 + let t1 = Sys.time () in 119 + for _i = 0 to n - 1 do ignore (fn a) done; 120 + let t2 = Sys.time () in 121 + (t2 -. t1) 122 + end 123 + 124 + let burn_period = 2.0 125 + let sizes = [ 16; 64; 256; 1024; 4096; 8192 ] 126 + 127 + let burn fn size = 128 + let cs = Mirage_crypto_rng.generate size in 129 + let (t1, i1) = 130 + let rec go it = 131 + let t = Time.time ~n:it fn cs in 132 + if t > 0.2 then (t, it) else go (it * 10) in 133 + go 10 in 134 + let iters = int_of_float (float i1 *. burn_period /. t1) in 135 + let time = Time.time ~n:iters fn cs in 136 + (iters, time, float (size * iters) /. time) 137 + 138 + let mb = 1024. *. 1024. 139 + 140 + let throughput title fn = 141 + Fmt.pr "\n## %s\n\n%!" title ; 142 + Fmt.pr "| block | MB/s |\n%!" ; 143 + Fmt.pr "| ----- | ------- |\n%!" ; 144 + List.iter begin fun size -> 145 + Gc.full_major (); 146 + let (_iters, _time, bw) = burn fn size in 147 + Fmt.pr "| %5d | %7.2f |\n%!" size (bw /. mb) 148 + end sizes 149 + 150 + let bm name fn = (name, fun () -> fn name) 151 + 152 + let count_period = 10. 153 + 154 + let count f n = 155 + ignore (f n); 156 + let i1 = 5 in 157 + let t1 = Time.time ~n:i1 f n in 158 + let iters = int_of_float (float i1 *. count_period /. t1) in 159 + let time = Time.time ~n:iters f n in 160 + (iters, time) 161 + 162 + let count title f to_str args = 163 + Printf.printf "\n## %s\n\n%!" title ; 164 + Printf.printf "| group | hs/s |\n%!" ; 165 + Printf.printf "| --------- | ------- |\n%!" ; 166 + args |> List.iter @@ fun arg -> 167 + Gc.full_major () ; 168 + let iters, time = count f arg in 169 + Printf.printf "| %s | %7.2f |\n%!" 170 + (to_str arg) (float iters /. time) 171 + 172 + let print_group group = 173 + let str = Fmt.to_to_string Tls.Core.pp_group group in 174 + let pad = 9 - String.length str in 175 + str ^ String.make pad ' ' 176 + 177 + let throughput = 178 + [ bm "tls-1.3, rsa/2048, x25519, aes-128-ccm-sha256" begin fun name -> 179 + let key = X509.Private_key.generate ~bits:2048 `RSA in 180 + let state = make ~groups:[ `X25519 ] ~cipher:`AES_128_CCM_SHA256 ~digest:`SHA256 ~key `TLS_1_3 `To_server in 181 + throughput name (to_consumer state) 182 + end 183 + ; bm "tls-1.3, rsa/2048, x25519, aes-128-gcm-sha256" begin fun name -> 184 + let key = X509.Private_key.generate ~bits:2048 `RSA in 185 + let state = make ~groups:[ `X25519 ] ~cipher:`AES_128_GCM_SHA256 ~digest:`SHA256 ~key `TLS_1_3 `To_server in 186 + throughput name (to_consumer state) 187 + end 188 + ; bm "tls-1.3, rsa/2048, x25519, aes-256-gcm-sha384" begin fun name -> 189 + let key = X509.Private_key.generate ~bits:2048 `RSA in 190 + let state = make ~groups:[ `X25519 ] ~cipher:`AES_256_GCM_SHA384 ~digest:`SHA256 ~key `TLS_1_3 `To_server in 191 + throughput name (to_consumer state) 192 + end 193 + ; bm "tls-1.3, rsa/2048, x25519, chacha20-poly1305-sha256" begin fun name -> 194 + let key = X509.Private_key.generate ~bits:2048 `RSA in 195 + let state = make ~groups:[ `X25519 ] ~cipher:`CHACHA20_POLY1305_SHA256 ~digest:`SHA256 ~key `TLS_1_3 `To_server in 196 + throughput name (to_consumer state) 197 + end 198 + ; bm "tls-1.2, rsa/2048, ffdhe2048, aes-128-ccm" begin fun name -> 199 + let key = X509.Private_key.generate ~bits:2048 `RSA in 200 + let state = make ~groups:[ `FFDHE2048 ] ~cipher:`DHE_RSA_WITH_AES_128_CCM ~digest:`SHA256 ~key `TLS_1_2 `To_server in 201 + throughput name (to_consumer state) 202 + end 203 + ; bm "tls-1.2, rsa/2048, ffdhe2048, aes-256-ccm" begin fun name -> 204 + let key = X509.Private_key.generate ~bits:2048 `RSA in 205 + let state = make ~groups:[ `FFDHE2048 ] ~cipher:`DHE_RSA_WITH_AES_256_CCM ~digest:`SHA256 ~key `TLS_1_2 `To_server in 206 + throughput name (to_consumer state) 207 + end 208 + ; bm "tls-1.2, rsa/2048, ffdhe2048, aes-128-gcm-sha256" begin fun name -> 209 + let key = X509.Private_key.generate ~bits:2048 `RSA in 210 + let state = make ~groups:[ `FFDHE2048 ] ~cipher:`DHE_RSA_WITH_AES_128_GCM_SHA256 ~digest:`SHA256 ~key `TLS_1_2 `To_server in 211 + throughput name (to_consumer state) 212 + end 213 + ; bm "tls-1.2, rsa/2048, ffdhe2048, aes-256-gcm-sha384" begin fun name -> 214 + let key = X509.Private_key.generate ~bits:2048 `RSA in 215 + let state = make ~groups:[ `FFDHE2048 ] ~cipher:`DHE_RSA_WITH_AES_256_GCM_SHA384 ~digest:`SHA256 ~key `TLS_1_2 `To_server in 216 + throughput name (to_consumer state) 217 + end 218 + ; bm "tls-1.2, rsa/2048, ffdhe2048, chacha20_poly1305_sha256" begin fun name -> 219 + let key = X509.Private_key.generate ~bits:2048 `RSA in 220 + let state = make ~groups:[ `FFDHE2048 ] ~cipher:`DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ~digest:`SHA256 ~key `TLS_1_2 `To_server in 221 + throughput name (to_consumer state) 222 + end 223 + ] 224 + 225 + and handshake = 226 + [ bm "tls-1.3 handshake, rsa2048" begin fun name -> 227 + let key = X509.Private_key.generate ~bits:2048 `RSA in 228 + count name begin fun group -> 229 + let state = make ~groups:[ group ] ~cipher:`CHACHA20_POLY1305_SHA256 ~digest:`SHA256 ~key `TLS_1_3 `To_server in 230 + ignore (once state None) 231 + end 232 + print_group 233 + ([ `X25519 ; `P256 ; `P384 ; `P521 ; `FFDHE2048 ; `FFDHE3072 ]) 234 + end 235 + ; bm "tls-1.3 handshake, ed25519" begin fun name -> 236 + let key = X509.Private_key.generate `ED25519 in 237 + count name begin fun group -> 238 + let state = make ~groups:[ group ] ~cipher:`CHACHA20_POLY1305_SHA256 ~digest:`SHA256 ~key `TLS_1_3 `To_server in 239 + ignore (once state None) 240 + end 241 + print_group 242 + ([ `X25519 ; `P256 ; `P384 ; `P521 ; `FFDHE2048 ; `FFDHE3072 ]) 243 + end 244 + ; bm "tls-1.3 handshake, p256" begin fun name -> 245 + let key = X509.Private_key.generate `P256 in 246 + count name begin fun group -> 247 + let state = make ~groups:[ group ] ~cipher:`CHACHA20_POLY1305_SHA256 ~digest:`SHA256 ~key `TLS_1_3 `To_server in 248 + ignore (once state None) 249 + end 250 + print_group 251 + ([ `X25519 ; `P256 ; `P384 ; `P521 ; `FFDHE2048 ; `FFDHE3072 ]) 252 + end 253 + ; bm "tls-1.2 handshake, rsa2048" begin fun name -> 254 + let key = X509.Private_key.generate ~bits:2048 `RSA in 255 + count name begin fun group -> 256 + let cipher = match group with 257 + | `FFDHE4096 | `FFDHE6144 | `FFDHE8192 | `FFDHE2048 | `FFDHE3072 -> `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 258 + | `X25519 | `P256 | `P384 | `P521 -> `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 259 + in 260 + let state = make ~groups:[ group ] ~cipher ~digest:`SHA256 ~key `TLS_1_2 `To_server in 261 + ignore (once state None) 262 + end 263 + print_group 264 + ([ `X25519 ; `P256; `P384 ; `P521 ; `FFDHE2048 ; `FFDHE3072 ]) 265 + end 266 + ] 267 + 268 + let run fns = 269 + List.iter (fun (_, fn) -> fn ()) fns 270 + 271 + let () = Mirage_crypto_rng_unix.use_default () 272 + 273 + let () = 274 + let seed = "0xdeadbeef" in 275 + let g = Mirage_crypto_rng.(create ~seed (module Fortuna)) in 276 + Mirage_crypto_rng.set_default_generator g; 277 + let bench = 278 + match Sys.argv.(1) with 279 + | exception Invalid_argument _ -> throughput @ handshake 280 + | "hs" -> handshake 281 + | "bw" -> throughput 282 + | _ -> invalid_arg "supported is: 'hs' (for handshake) or 'bw' (for bandwidth)" 283 + in 284 + run bench
+14
vendor/opam/tls/certificates/bar.pem
··· 1 + -----BEGIN CERTIFICATE----- 2 + MIICHTCCAYYCCQDyqsjENH2CvTANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJB 3 + VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 4 + cyBQdHkgTHRkMQwwCgYDVQQDDANiYXIwHhcNMTQwODExMTIxMDEwWhcNMTUwODEx 5 + MTIxMDEwWjBTMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8G 6 + A1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDDANiYXIwgZ8w 7 + DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZASN7mvCGUPaKrXrb42DcAf0F8D+M0 8 + ksOqL1U+TV4xQ0aJwm8r5o4A0oiw46v2/hGIRdlJiYUS8ZLL5J/VsIMfAcstJ02z 9 + pjj1vvs86Bq2tVk5NEQET+3WyhVPdr+9UlYIu1UKObvS7RLm1x+fhLohql4hgBUC 10 + ZxqrBJr4ZA2hAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAci6xzomZWURSro7/B8Hy 11 + DgoMF15tcocsyeFnxLBGqXyg2RQnvZXjv7DFkQgieDFqXvAFgxG+bcZzBFrKHI6A 12 + FKH9IeBpgtVPVbnHJYMpEShzOSyc/8MFSuqMqo9a/XWK7VTguZqzTVSoyE06S6AP 13 + 10W+CBZBT+5Gah6I9rsLDNo= 14 + -----END CERTIFICATE-----
+4157
vendor/opam/tls/certificates/ca-root-nss-short.crt
··· 1 + -----BEGIN CERTIFICATE----- 2 + MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290 3 + IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB 4 + IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA 5 + Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO 6 + BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi 7 + MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ 8 + ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 9 + CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ 10 + 8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6 11 + zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y 12 + fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7 13 + w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc 14 + G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k 15 + epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q 16 + laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ 17 + QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU 18 + fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826 19 + YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w 20 + ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY 21 + gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe 22 + MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0 23 + IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy 24 + dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw 25 + czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0 26 + dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl 27 + aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC 28 + AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg 29 + b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB 30 + ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc 31 + nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg 32 + 18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c 33 + gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl 34 + Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY 35 + sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T 36 + SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF 37 + CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum 38 + GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk 39 + zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW 40 + omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD 41 + -----END CERTIFICATE----- 42 + 43 + -----BEGIN CERTIFICATE----- 44 + MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB 45 + VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp 46 + bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R 47 + dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw 48 + MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy 49 + dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52 50 + ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM 51 + EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 52 + AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj 53 + lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ 54 + znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH 55 + 2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1 56 + k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs 57 + 2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD 58 + VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC 59 + AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG 60 + KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+ 61 + 8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R 62 + FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS 63 + mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE 64 + DNuxUCAKGkq6ahq97BvIxYSazQ== 65 + -----END CERTIFICATE----- 66 + 67 + -----BEGIN CERTIFICATE----- 68 + MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx 69 + CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp 70 + ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa 71 + QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw 72 + NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft 73 + ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu 74 + QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq 75 + hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG 76 + qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL 77 + fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ 78 + Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4 79 + Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ 80 + 54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b 81 + MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j 82 + ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej 83 + YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt 84 + A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF 85 + rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ 86 + pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 87 + AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB 88 + lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy 89 + YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50 90 + 7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs 91 + YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6 92 + xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc 93 + unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/ 94 + Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp 95 + ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42 96 + gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0 97 + jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+ 98 + XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD 99 + W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/ 100 + RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r 101 + MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk 102 + BYn8eNZcLCZDqQ== 103 + -----END CERTIFICATE----- 104 + 105 + -----BEGIN CERTIFICATE----- 106 + MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE 107 + AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x 108 + CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW 109 + MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF 110 + RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC 111 + AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7 112 + 09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7 113 + XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P 114 + Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK 115 + t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb 116 + X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28 117 + MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU 118 + fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI 119 + 2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH 120 + K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae 121 + ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP 122 + BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ 123 + MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw 124 + RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv 125 + bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm 126 + fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3 127 + gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe 128 + I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i 129 + 5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi 130 + ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn 131 + MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ 132 + o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6 133 + zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN 134 + GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt 135 + r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK 136 + Z05phkOTOPu220+DkdRgfks+KzgHVZhepA== 137 + -----END CERTIFICATE----- 138 + 139 + -----BEGIN CERTIFICATE----- 140 + MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE 141 + BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w 142 + MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 143 + IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC 144 + SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 145 + ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB 146 + MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv 147 + UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX 148 + 4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 149 + KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ 150 + gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb 151 + rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ 152 + 51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F 153 + be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe 154 + KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F 155 + v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn 156 + fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 157 + jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz 158 + ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt 159 + ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL 160 + e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 161 + jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz 162 + WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V 163 + SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j 164 + pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX 165 + X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok 166 + fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R 167 + K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU 168 + ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU 169 + LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT 170 + LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== 171 + -----END CERTIFICATE----- 172 + 173 + -----BEGIN CERTIFICATE----- 174 + MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU 175 + MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs 176 + IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 177 + MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux 178 + FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h 179 + bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v 180 + dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt 181 + H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 182 + uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX 183 + mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX 184 + a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN 185 + E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 186 + WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD 187 + VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 188 + Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU 189 + cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx 190 + IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN 191 + AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH 192 + YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 193 + 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC 194 + Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX 195 + c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a 196 + mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= 197 + -----END CERTIFICATE----- 198 + 199 + -----BEGIN CERTIFICATE----- 200 + MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU 201 + MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 202 + b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw 203 + MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML 204 + QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD 205 + VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA 206 + A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul 207 + CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n 208 + tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl 209 + dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch 210 + PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC 211 + +Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O 212 + BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E 213 + BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl 214 + MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk 215 + ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB 216 + IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X 217 + 7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz 218 + 43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY 219 + eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl 220 + pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA 221 + WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= 222 + -----END CERTIFICATE----- 223 + 224 + -----BEGIN CERTIFICATE----- 225 + MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU 226 + MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 227 + b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx 228 + MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB 229 + ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV 230 + BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC 231 + AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV 232 + 6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX 233 + GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP 234 + dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH 235 + 1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF 236 + 62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW 237 + BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw 238 + AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL 239 + MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU 240 + cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv 241 + b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 242 + IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ 243 + iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao 244 + GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh 245 + 4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm 246 + XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= 247 + -----END CERTIFICATE----- 248 + 249 + -----BEGIN CERTIFICATE----- 250 + MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU 251 + MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 252 + b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 253 + MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK 254 + EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh 255 + BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B 256 + AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq 257 + xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G 258 + 87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i 259 + 2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U 260 + WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 261 + 0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G 262 + A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T 263 + AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr 264 + pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL 265 + ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm 266 + aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv 267 + hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm 268 + hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X 269 + dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 270 + P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y 271 + iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no 272 + xqE= 273 + -----END CERTIFICATE----- 274 + 275 + -----BEGIN CERTIFICATE----- 276 + MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE 277 + BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz 278 + dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL 279 + MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp 280 + cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 281 + AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP 282 + Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr 283 + ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL 284 + MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 285 + yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr 286 + VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ 287 + nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ 288 + KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG 289 + XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj 290 + vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt 291 + Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g 292 + N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC 293 + nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= 294 + -----END CERTIFICATE----- 295 + 296 + -----BEGIN CERTIFICATE----- 297 + MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE 298 + BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz 299 + dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL 300 + MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp 301 + cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 302 + AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y 303 + YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua 304 + kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL 305 + QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp 306 + 6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG 307 + yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i 308 + QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ 309 + KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO 310 + tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu 311 + QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ 312 + Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u 313 + olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 314 + x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= 315 + -----END CERTIFICATE----- 316 + 317 + -----BEGIN CERTIFICATE----- 318 + MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE 319 + BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz 320 + dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG 321 + A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U 322 + cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf 323 + qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ 324 + JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ 325 + +jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS 326 + s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 327 + HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 328 + 70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG 329 + V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S 330 + qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S 331 + 5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia 332 + C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX 333 + OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE 334 + FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ 335 + BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 336 + KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg 337 + Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B 338 + 8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ 339 + MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc 340 + 0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ 341 + u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF 342 + u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH 343 + YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 344 + GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO 345 + RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e 346 + KeC2uAloGRwYQw== 347 + -----END CERTIFICATE----- 348 + 349 + -----BEGIN CERTIFICATE----- 350 + MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC 351 + VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ 352 + cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ 353 + BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt 354 + VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D 355 + 0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 356 + ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G 357 + A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G 358 + A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs 359 + aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I 360 + flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== 361 + -----END CERTIFICATE----- 362 + 363 + -----BEGIN CERTIFICATE----- 364 + MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc 365 + MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP 366 + bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 367 + MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft 368 + ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg 369 + Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP 370 + ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk 371 + hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym 372 + 1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW 373 + OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb 374 + 2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko 375 + O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw 376 + AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU 377 + AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB 378 + BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF 379 + Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb 380 + LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir 381 + oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C 382 + MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds 383 + sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 384 + -----END CERTIFICATE----- 385 + 386 + -----BEGIN CERTIFICATE----- 387 + MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc 388 + MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP 389 + bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 390 + MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft 391 + ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg 392 + Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP 393 + ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC 394 + 206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci 395 + KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 396 + JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 397 + BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e 398 + Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B 399 + PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 400 + Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq 401 + Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ 402 + o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 403 + +L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj 404 + YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj 405 + FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE 406 + AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn 407 + xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 408 + LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc 409 + obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 410 + CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe 411 + IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA 412 + DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F 413 + AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX 414 + Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb 415 + AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl 416 + Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw 417 + RY8mkaKO/qk= 418 + -----END CERTIFICATE----- 419 + 420 + -----BEGIN CERTIFICATE----- 421 + MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc 422 + MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp 423 + b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT 424 + AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs 425 + aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H 426 + j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K 427 + f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55 428 + IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw 429 + FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht 430 + QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm 431 + /qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ 432 + k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ 433 + MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC 434 + seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD 435 + ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ 436 + hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+ 437 + eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U 438 + DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj 439 + B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL 440 + rosot4LKGAfmt1t06SAZf7IbiVQ= 441 + -----END CERTIFICATE----- 442 + 443 + -----BEGIN CERTIFICATE----- 444 + MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE 445 + BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h 446 + cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy 447 + MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg 448 + Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi 449 + MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 450 + thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM 451 + cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG 452 + L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i 453 + NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h 454 + X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b 455 + m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy 456 + Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja 457 + EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T 458 + KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF 459 + 6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh 460 + OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD 461 + VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD 462 + VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp 463 + cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv 464 + ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl 465 + AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF 466 + 661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 467 + am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 468 + ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 469 + PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS 470 + 3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k 471 + SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF 472 + 3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM 473 + ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g 474 + StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz 475 + Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB 476 + jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V 477 + -----END CERTIFICATE----- 478 + 479 + -----BEGIN CERTIFICATE----- 480 + MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ 481 + RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD 482 + VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX 483 + DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y 484 + ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy 485 + VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr 486 + mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr 487 + IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK 488 + mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu 489 + XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy 490 + dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye 491 + jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 492 + BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 493 + DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 494 + 9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx 495 + jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 496 + Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz 497 + ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS 498 + R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp 499 + -----END CERTIFICATE----- 500 + 501 + -----BEGIN CERTIFICATE----- 502 + MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd 503 + MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg 504 + Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL 505 + MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD 506 + VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP 507 + ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0 508 + ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX 509 + l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB 510 + HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B 511 + 5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3 512 + WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw 513 + AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD 514 + AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP 515 + gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+ 516 + DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu 517 + BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs 518 + h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk 519 + LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho 520 + -----END CERTIFICATE----- 521 + 522 + -----BEGIN CERTIFICATE----- 523 + MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd 524 + MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg 525 + Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow 526 + TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw 527 + HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB 528 + BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr 529 + 6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV 530 + L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 531 + 1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx 532 + MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ 533 + QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB 534 + arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr 535 + Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi 536 + FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS 537 + P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN 538 + 9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP 539 + AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz 540 + uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h 541 + 9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s 542 + A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t 543 + OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo 544 + +fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 545 + KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 546 + DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us 547 + H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ 548 + I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 549 + 5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h 550 + 3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz 551 + Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= 552 + -----END CERTIFICATE----- 553 + 554 + -----BEGIN CERTIFICATE----- 555 + MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd 556 + MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg 557 + Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL 558 + MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD 559 + VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP 560 + ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg 561 + isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z 562 + NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI 563 + +MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R 564 + hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+ 565 + mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw 566 + AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD 567 + AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP 568 + Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s 569 + EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2 570 + mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC 571 + e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow 572 + dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 573 + -----END CERTIFICATE----- 574 + 575 + -----BEGIN CERTIFICATE----- 576 + MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd 577 + MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg 578 + Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow 579 + TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw 580 + HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB 581 + BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y 582 + ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E 583 + N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 584 + tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX 585 + 0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c 586 + /3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X 587 + KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY 588 + zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS 589 + O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D 590 + 34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP 591 + K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 592 + AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv 593 + Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj 594 + QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV 595 + cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS 596 + IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 597 + HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa 598 + O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv 599 + 033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u 600 + dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE 601 + kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 602 + 3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD 603 + u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq 604 + 4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= 605 + -----END CERTIFICATE----- 606 + 607 + -----BEGIN CERTIFICATE----- 608 + MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET 609 + MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE 610 + AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw 611 + CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg 612 + YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 613 + ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE 614 + Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX 615 + mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD 616 + XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW 617 + S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp 618 + FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw 619 + AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD 620 + AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu 621 + ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z 622 + ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv 623 + Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw 624 + DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6 625 + yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq 626 + EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ 627 + CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB 628 + EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN 629 + PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag= 630 + -----END CERTIFICATE----- 631 + 632 + -----BEGIN CERTIFICATE----- 633 + MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn 634 + MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL 635 + ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg 636 + b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa 637 + MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB 638 + ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw 639 + IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B 640 + AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb 641 + unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d 642 + BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq 643 + 7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 644 + 0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX 645 + roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG 646 + A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j 647 + aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p 648 + 26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA 649 + BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud 650 + EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN 651 + BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz 652 + aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB 653 + AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd 654 + p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi 655 + 1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc 656 + XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 657 + eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu 658 + tGWaIZDgqtCYvDi1czyL+Nw= 659 + -----END CERTIFICATE----- 660 + 661 + -----BEGIN CERTIFICATE----- 662 + MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn 663 + MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL 664 + ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo 665 + YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 666 + MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy 667 + NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G 668 + A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA 669 + A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 670 + Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s 671 + QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV 672 + eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 673 + B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh 674 + z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T 675 + AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i 676 + ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w 677 + TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH 678 + MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD 679 + VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE 680 + VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh 681 + bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B 682 + AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM 683 + bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi 684 + ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG 685 + VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c 686 + ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ 687 + AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== 688 + -----END CERTIFICATE----- 689 + 690 + -----BEGIN CERTIFICATE----- 691 + MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV 692 + BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X 693 + DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ 694 + BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 695 + DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 696 + QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny 697 + gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw 698 + zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q 699 + 130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 700 + JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw 701 + DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw 702 + ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT 703 + AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj 704 + AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG 705 + 9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h 706 + bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc 707 + fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu 708 + HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w 709 + t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw 710 + WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== 711 + -----END CERTIFICATE----- 712 + 713 + -----BEGIN CERTIFICATE----- 714 + MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET 715 + MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk 716 + BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4 717 + Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl 718 + cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0 719 + aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP 720 + ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY 721 + F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N 722 + 8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe 723 + rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K 724 + /OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu 725 + 7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC 726 + 28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6 727 + lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E 728 + nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB 729 + 0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09 730 + 5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj 731 + WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN 732 + jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ 733 + KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s 734 + ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM 735 + OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q 736 + 619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn 737 + 2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj 738 + o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v 739 + nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG 740 + 5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq 741 + pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb 742 + dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0 743 + BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5 744 + -----END CERTIFICATE----- 745 + 746 + -----BEGIN CERTIFICATE----- 747 + MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw 748 + PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz 749 + cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 750 + MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz 751 + IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ 752 + ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR 753 + VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL 754 + kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd 755 + EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas 756 + H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 757 + HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud 758 + DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 759 + QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu 760 + Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ 761 + AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 762 + yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR 763 + FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA 764 + ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB 765 + kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 766 + l7+ijrRU 767 + -----END CERTIFICATE----- 768 + 769 + -----BEGIN CERTIFICATE----- 770 + MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT 771 + AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD 772 + QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP 773 + MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC 774 + ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do 775 + 0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ 776 + UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d 777 + RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ 778 + OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv 779 + JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C 780 + AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O 781 + BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ 782 + LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY 783 + MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ 784 + 44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I 785 + Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw 786 + i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN 787 + 9u6wWk5JRFRYX0KD 788 + -----END CERTIFICATE----- 789 + 790 + -----BEGIN CERTIFICATE----- 791 + MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM 792 + MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD 793 + QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM 794 + MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD 795 + QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E 796 + jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo 797 + ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI 798 + ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu 799 + Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg 800 + AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 801 + HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA 802 + uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa 803 + TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg 804 + xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q 805 + CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x 806 + O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs 807 + 6GAqm4VKQPNriiTsBhYscw== 808 + -----END CERTIFICATE----- 809 + 810 + -----BEGIN CERTIFICATE----- 811 + MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM 812 + MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D 813 + ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU 814 + cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 815 + WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg 816 + Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw 817 + IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B 818 + AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH 819 + UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM 820 + TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU 821 + BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM 822 + kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x 823 + AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV 824 + HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV 825 + HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y 826 + sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL 827 + I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 828 + J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY 829 + VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 830 + 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= 831 + -----END CERTIFICATE----- 832 + 833 + -----BEGIN CERTIFICATE----- 834 + MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD 835 + VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 836 + IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 837 + MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz 838 + IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz 839 + MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj 840 + dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw 841 + EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp 842 + MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G 843 + CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 844 + 28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq 845 + VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q 846 + DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR 847 + 5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL 848 + ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a 849 + Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl 850 + UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s 851 + +12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 852 + Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj 853 + ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx 854 + hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV 855 + HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 856 + +HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN 857 + YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t 858 + L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy 859 + ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt 860 + IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV 861 + HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w 862 + DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW 863 + PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF 864 + 5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 865 + glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH 866 + FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 867 + pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD 868 + xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG 869 + tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq 870 + jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De 871 + fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg 872 + OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ 873 + d0jQ 874 + -----END CERTIFICATE----- 875 + 876 + -----BEGIN CERTIFICATE----- 877 + MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD 878 + TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2 879 + MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF 880 + Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB 881 + DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh 882 + IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6 883 + dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO 884 + V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC 885 + GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN 886 + v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB 887 + AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB 888 + Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO 889 + 76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK 890 + OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH 891 + ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi 892 + yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL 893 + buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj 894 + 2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE= 895 + -----END CERTIFICATE----- 896 + 897 + -----BEGIN CERTIFICATE----- 898 + MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb 899 + MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow 900 + GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj 901 + YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL 902 + MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE 903 + BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM 904 + GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP 905 + ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua 906 + BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe 907 + 3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 908 + YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR 909 + rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm 910 + ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU 911 + oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF 912 + MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v 913 + QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t 914 + b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF 915 + AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q 916 + GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz 917 + Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 918 + G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi 919 + l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 920 + smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== 921 + -----END CERTIFICATE----- 922 + 923 + -----BEGIN CERTIFICATE----- 924 + MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB 925 + gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G 926 + A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV 927 + BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw 928 + MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl 929 + YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P 930 + RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 931 + aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 932 + UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI 933 + 2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 934 + Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp 935 + +2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ 936 + DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O 937 + nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW 938 + /zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g 939 + PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u 940 + QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY 941 + SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv 942 + IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ 943 + RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 944 + zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd 945 + BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB 946 + ZQ== 947 + -----END CERTIFICATE----- 948 + 949 + -----BEGIN CERTIFICATE----- 950 + MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL 951 + MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE 952 + BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT 953 + IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw 954 + MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy 955 + ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N 956 + T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv 957 + biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR 958 + FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J 959 + cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW 960 + BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ 961 + BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm 962 + fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv 963 + GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= 964 + -----END CERTIFICATE----- 965 + 966 + -----BEGIN CERTIFICATE----- 967 + MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb 968 + MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow 969 + GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp 970 + ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow 971 + fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G 972 + A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV 973 + BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB 974 + BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM 975 + cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S 976 + HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 977 + CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk 978 + 3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz 979 + 6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV 980 + HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud 981 + EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv 982 + Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw 983 + Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww 984 + DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 985 + 5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj 986 + Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI 987 + gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ 988 + aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl 989 + izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= 990 + -----END CERTIFICATE----- 991 + 992 + -----BEGIN CERTIFICATE----- 993 + MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb 994 + MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow 995 + GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 996 + aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla 997 + MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO 998 + BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD 999 + VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B 1000 + AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW 1001 + fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt 1002 + TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL 1003 + fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW 1004 + 1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 1005 + kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G 1006 + A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD 1007 + VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v 1008 + ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo 1009 + dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu 1010 + Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ 1011 + HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 1012 + pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS 1013 + jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ 1014 + xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn 1015 + dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi 1016 + -----END CERTIFICATE----- 1017 + 1018 + -----BEGIN CERTIFICATE----- 1019 + MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0 1020 + MRMwEQYDVQQDEwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQG 1021 + EwJJTDAeFw0wNDAzMjQxMTMyMThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMT 1022 + CkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNpZ24xCzAJBgNVBAYTAklMMIIBIjAN 1023 + BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49qROR+WCf4C9DklBKK 1024 + 8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTyP2Q2 1025 + 98CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb 1026 + 2CEJKHxNGGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxC 1027 + ejVb7Us6eva1jsz/D3zkYDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7Kpi 1028 + Xd3DTKaCQeQzC6zJMw9kglcq/QytNuEMrkvF7zuZ2SOzW120V+x0cAwqTwIDAQAB 1029 + o4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Zl 1030 + ZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0PAQH/BAQD 1031 + AgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRL 1032 + AZs+VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWd 1033 + foPPbrxHbvUanlR2QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0M 1034 + cXS6hMTXcpuEfDhOZAYnKuGntewImbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq 1035 + 8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb/627HOkthIDYIb6FUtnUdLlp 1036 + hbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VGzT2ouvDzuFYk 1037 + Res3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U 1038 + AGegcQCCSA== 1039 + -----END CERTIFICATE----- 1040 + 1041 + -----BEGIN CERTIFICATE----- 1042 + MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw 1043 + PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu 1044 + MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx 1045 + GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL 1046 + MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf 1047 + HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh 1048 + gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW 1049 + v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue 1050 + Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr 1051 + 9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt 1052 + 6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7 1053 + MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl 1054 + Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58 1055 + ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq 1056 + hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p 1057 + iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC 1058 + dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL 1059 + kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL 1060 + hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz 1061 + OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== 1062 + -----END CERTIFICATE----- 1063 + 1064 + -----BEGIN CERTIFICATE----- 1065 + MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG 1066 + A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh 1067 + bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE 1068 + ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS 1069 + b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 1070 + 7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS 1071 + J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y 1072 + HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP 1073 + t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz 1074 + FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY 1075 + XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ 1076 + MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw 1077 + hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js 1078 + MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA 1079 + A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj 1080 + Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx 1081 + XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o 1082 + omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc 1083 + A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW 1084 + WL1WMRJOEcgh4LMRkWXbtKaIOM5V 1085 + -----END CERTIFICATE----- 1086 + 1087 + -----BEGIN CERTIFICATE----- 1088 + MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc 1089 + MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj 1090 + IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB 1091 + IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE 1092 + RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl 1093 + U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 1094 + IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU 1095 + ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC 1096 + QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr 1097 + rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S 1098 + NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc 1099 + QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH 1100 + txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP 1101 + BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC 1102 + AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp 1103 + tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa 1104 + IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl 1105 + 6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ 1106 + xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU 1107 + Cm26OWMohpLzGITY+9HPBVZkVw== 1108 + -----END CERTIFICATE----- 1109 + 1110 + -----BEGIN CERTIFICATE----- 1111 + MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl 1112 + MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 1113 + d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv 1114 + b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG 1115 + EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl 1116 + cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi 1117 + MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c 1118 + JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP 1119 + mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ 1120 + wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 1121 + VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ 1122 + AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB 1123 + AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW 1124 + BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun 1125 + pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC 1126 + dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf 1127 + fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm 1128 + NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx 1129 + H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe 1130 + +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== 1131 + -----END CERTIFICATE----- 1132 + 1133 + -----BEGIN CERTIFICATE----- 1134 + MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh 1135 + MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 1136 + d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD 1137 + QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT 1138 + MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j 1139 + b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG 1140 + 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB 1141 + CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 1142 + nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt 1143 + 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P 1144 + T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 1145 + gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO 1146 + BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR 1147 + TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw 1148 + DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr 1149 + hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg 1150 + 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF 1151 + PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls 1152 + YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk 1153 + CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= 1154 + -----END CERTIFICATE----- 1155 + 1156 + -----BEGIN CERTIFICATE----- 1157 + MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs 1158 + MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 1159 + d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j 1160 + ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL 1161 + MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 1162 + LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug 1163 + RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm 1164 + +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW 1165 + PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM 1166 + xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB 1167 + Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 1168 + hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg 1169 + EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF 1170 + MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA 1171 + FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec 1172 + nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z 1173 + eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF 1174 + hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 1175 + Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe 1176 + vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep 1177 + +OkuE6N36B9K 1178 + -----END CERTIFICATE----- 1179 + 1180 + -----BEGIN CERTIFICATE----- 1181 + MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV 1182 + UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL 1183 + EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ 1184 + BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x 1185 + ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg 1186 + bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ 1187 + j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV 1188 + Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG 1189 + SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx 1190 + JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI 1191 + RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw 1192 + MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 1193 + fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i 1194 + +DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG 1195 + SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN 1196 + QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ 1197 + gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl 1198 + -----END CERTIFICATE----- 1199 + 1200 + -----BEGIN CERTIFICATE----- 1201 + MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV 1202 + UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL 1203 + EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ 1204 + BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x 1205 + ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/ 1206 + k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso 1207 + LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o 1208 + TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG 1209 + SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx 1210 + JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI 1211 + RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3 1212 + MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C 1213 + TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5 1214 + WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG 1215 + SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR 1216 + xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL 1217 + B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID 1218 + -----END CERTIFICATE----- 1219 + 1220 + -----BEGIN CERTIFICATE----- 1221 + MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb 1222 + MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx 1223 + ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w 1224 + MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD 1225 + VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx 1226 + FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 1227 + MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu 1228 + ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 1229 + gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH 1230 + fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a 1231 + ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT 1232 + ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF 1233 + MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk 1234 + c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto 1235 + dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt 1236 + aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI 1237 + hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk 1238 + QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ 1239 + h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq 1240 + nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR 1241 + rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 1242 + 9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= 1243 + -----END CERTIFICATE----- 1244 + 1245 + -----BEGIN CERTIFICATE----- 1246 + MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ 1247 + MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT 1248 + DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow 1249 + PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD 1250 + Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB 1251 + AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O 1252 + rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq 1253 + OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b 1254 + xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw 1255 + 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD 1256 + aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV 1257 + HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG 1258 + SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 1259 + ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr 1260 + AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz 1261 + R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 1262 + JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo 1263 + Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ 1264 + -----END CERTIFICATE----- 1265 + 1266 + -----BEGIN CERTIFICATE----- 1267 + MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1 1268 + MQswCQYDVQQGEwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxp 1269 + Z2kgQS5TLjE8MDoGA1UEAxMzZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZp 1270 + a2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3MDEwNDExMzI0OFoXDTE3MDEwNDEx 1271 + MzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0cm9uaWsgQmlsZ2kg 1272 + R3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9uaWsg 1273 + U2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQAD 1274 + ggEPADCCAQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdU 1275 + MZTe1RK6UxYC6lhj71vY8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlT 1276 + L/jDj/6z/P2douNffb7tC+Bg62nsM+3YjfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H 1277 + 5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAIJjjcJRFHLfO6IxClv7wC 1278 + 90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk9Ok0oSy1 1279 + c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/ 1280 + BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoE 1281 + VtstxNulMA0GCSqGSIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLP 1282 + qk/CaOv/gKlR6D1id4k9CnU58W5dF4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S 1283 + /wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwqD2fK/A+JYZ1lpTzlvBNbCNvj 1284 + /+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4Vwpm+Vganf2X 1285 + KWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq 1286 + fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX 1287 + -----END CERTIFICATE----- 1288 + 1289 + -----BEGIN CERTIFICATE----- 1290 + MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV 1291 + BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx 1292 + c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt 1293 + ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4 1294 + MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg 1295 + SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl 1296 + a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi 1297 + MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h 1298 + 4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk 1299 + tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s 1300 + tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL 1301 + dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4 1302 + c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um 1303 + TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z 1304 + +kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O 1305 + Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW 1306 + OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW 1307 + fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2 1308 + l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB 1309 + /wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw 1310 + FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+ 1311 + 8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI 1312 + 6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO 1313 + TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME 1314 + wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY 1315 + Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn 1316 + xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q 1317 + DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q 1318 + Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t 1319 + hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4 1320 + 7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7 1321 + QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT 1322 + -----END CERTIFICATE----- 1323 + 1324 + -----BEGIN CERTIFICATE----- 1325 + MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB 1326 + 8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy 1327 + dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 1328 + YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 1329 + dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh 1330 + IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD 1331 + LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG 1332 + EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g 1333 + KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD 1334 + ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu 1335 + bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg 1336 + ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN 1337 + BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R 1338 + 85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm 1339 + 4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV 1340 + HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd 1341 + QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t 1342 + lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB 1343 + o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E 1344 + BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4 1345 + opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo 1346 + dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW 1347 + ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN 1348 + AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y 1349 + /X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k 1350 + SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy 1351 + Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS 1352 + Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl 1353 + nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI= 1354 + -----END CERTIFICATE----- 1355 + 1356 + -----BEGIN CERTIFICATE----- 1357 + MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 1358 + MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 1359 + czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG 1360 + CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy 1361 + MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl 1362 + ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS 1363 + b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB 1364 + AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy 1365 + euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO 1366 + bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw 1367 + WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d 1368 + MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE 1369 + 1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD 1370 + VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ 1371 + zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB 1372 + BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF 1373 + BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV 1374 + v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG 1375 + E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u 1376 + uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW 1377 + iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v 1378 + GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= 1379 + -----END CERTIFICATE----- 1380 + 1381 + -----BEGIN CERTIFICATE----- 1382 + MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC 1383 + VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 1384 + Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW 1385 + KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl 1386 + cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw 1387 + NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw 1388 + NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy 1389 + ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV 1390 + BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ 1391 + KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo 1392 + Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 1393 + 4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 1394 + KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI 1395 + rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi 1396 + 94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB 1397 + sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi 1398 + gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo 1399 + kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE 1400 + vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA 1401 + A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t 1402 + O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua 1403 + AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP 1404 + 9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ 1405 + eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m 1406 + 0vdXcDazv/wor3ElhVsT/h5/WrQ8 1407 + -----END CERTIFICATE----- 1408 + 1409 + -----BEGIN CERTIFICATE----- 1410 + MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML 1411 + RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp 1412 + bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 1413 + IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp 1414 + ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy 1415 + MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 1416 + LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp 1417 + YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG 1418 + A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp 1419 + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq 1420 + K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe 1421 + sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX 1422 + MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT 1423 + XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ 1424 + HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH 1425 + 4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA 1426 + vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G 1427 + CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA 1428 + WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo 1429 + oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ 1430 + h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 1431 + f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN 1432 + B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy 1433 + vUxFnmG6v4SBkgPR0ml8xQ== 1434 + -----END CERTIFICATE----- 1435 + 1436 + -----BEGIN CERTIFICATE----- 1437 + MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC 1438 + VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u 1439 + ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc 1440 + KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u 1441 + ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 1442 + MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE 1443 + ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j 1444 + b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF 1445 + bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg 1446 + U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA 1447 + A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ 1448 + I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 1449 + wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC 1450 + AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb 1451 + oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 1452 + BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p 1453 + dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk 1454 + MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp 1455 + b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu 1456 + dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 1457 + MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi 1458 + E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa 1459 + MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI 1460 + hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN 1461 + 95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd 1462 + 2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= 1463 + -----END CERTIFICATE----- 1464 + 1465 + -----BEGIN CERTIFICATE----- 1466 + MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe 1467 + MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 1468 + ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe 1469 + Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw 1470 + IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL 1471 + SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF 1472 + AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH 1473 + SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh 1474 + ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X 1475 + DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 1476 + TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ 1477 + fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA 1478 + sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU 1479 + WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS 1480 + nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH 1481 + dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip 1482 + NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC 1483 + AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF 1484 + MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH 1485 + ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB 1486 + uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl 1487 + PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP 1488 + JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ 1489 + gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 1490 + j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 1491 + 5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB 1492 + o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS 1493 + /jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z 1494 + Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE 1495 + W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D 1496 + hNQ+IIX3Sj0rnP0qCglN6oH4EZw= 1497 + -----END CERTIFICATE----- 1498 + 1499 + -----BEGIN CERTIFICATE----- 1500 + MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV 1501 + UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy 1502 + dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 1503 + MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx 1504 + dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B 1505 + AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f 1506 + BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A 1507 + cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC 1508 + AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ 1509 + MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm 1510 + aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw 1511 + ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj 1512 + IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF 1513 + MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA 1514 + A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 1515 + 7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh 1516 + 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 1517 + -----END CERTIFICATE----- 1518 + 1519 + -----BEGIN CERTIFICATE----- 1520 + MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc 1521 + MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT 1522 + ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw 1523 + MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j 1524 + LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ 1525 + KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo 1526 + RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu 1527 + WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw 1528 + Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD 1529 + AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK 1530 + eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM 1531 + zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ 1532 + WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN 1533 + /Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== 1534 + -----END CERTIFICATE----- 1535 + 1536 + -----BEGIN CERTIFICATE----- 1537 + MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV 1538 + UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj 1539 + dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 1540 + NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD 1541 + VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B 1542 + AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G 1543 + vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ 1544 + BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C 1545 + AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX 1546 + MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl 1547 + IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw 1548 + NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq 1549 + y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF 1550 + MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA 1551 + A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy 1552 + 0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 1553 + E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN 1554 + -----END CERTIFICATE----- 1555 + 1556 + -----BEGIN CERTIFICATE----- 1557 + MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc 1558 + MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT 1559 + ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw 1560 + MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj 1561 + dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l 1562 + c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC 1563 + UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc 1564 + 58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ 1565 + o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH 1566 + MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr 1567 + aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA 1568 + A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA 1569 + Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv 1570 + 8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV 1571 + -----END CERTIFICATE----- 1572 + 1573 + -----BEGIN CERTIFICATE----- 1574 + MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx 1575 + IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 1576 + dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 1577 + MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w 1578 + HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx 1579 + IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1 1580 + dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 1581 + MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w 1582 + ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u 1583 + Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY 1584 + rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z 1585 + hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay 1586 + BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL 1587 + iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb 1588 + AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv 1589 + bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0 1590 + MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E 1591 + FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n 1592 + VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq 1593 + u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m 1594 + hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl 1595 + ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp 1596 + QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5 1597 + quGnM/b9Sh/22WA= 1598 + -----END CERTIFICATE----- 1599 + 1600 + -----BEGIN CERTIFICATE----- 1601 + MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT 1602 + MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i 1603 + YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG 1604 + EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg 1605 + R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 1606 + 9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq 1607 + fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv 1608 + iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU 1609 + 1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ 1610 + bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW 1611 + MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA 1612 + ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l 1613 + uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn 1614 + Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS 1615 + tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF 1616 + PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un 1617 + hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV 1618 + 5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== 1619 + -----END CERTIFICATE----- 1620 + 1621 + -----BEGIN CERTIFICATE----- 1622 + MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW 1623 + MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs 1624 + IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG 1625 + EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg 1626 + R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A 1627 + PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 1628 + Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL 1629 + TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL 1630 + 5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 1631 + S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe 1632 + 2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE 1633 + FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap 1634 + EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td 1635 + EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv 1636 + /NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN 1637 + A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 1638 + abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF 1639 + I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz 1640 + 4iIprn2DQKi6bA== 1641 + -----END CERTIFICATE----- 1642 + 1643 + -----BEGIN CERTIFICATE----- 1644 + MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY 1645 + MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo 1646 + R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx 1647 + MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK 1648 + Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp 1649 + ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 1650 + AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 1651 + AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA 1652 + ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 1653 + 7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W 1654 + kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI 1655 + mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G 1656 + A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ 1657 + KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 1658 + 6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl 1659 + 4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K 1660 + oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj 1661 + UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU 1662 + AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= 1663 + -----END CERTIFICATE----- 1664 + 1665 + -----BEGIN CERTIFICATE----- 1666 + MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL 1667 + MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj 1668 + KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 1669 + MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 1670 + eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV 1671 + BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw 1672 + NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV 1673 + BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH 1674 + MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL 1675 + So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal 1676 + tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO 1677 + BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG 1678 + CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT 1679 + qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz 1680 + rD6ogRLQy7rQkgu2npaqBA+K 1681 + -----END CERTIFICATE----- 1682 + 1683 + -----BEGIN CERTIFICATE----- 1684 + MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB 1685 + mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT 1686 + MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s 1687 + eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv 1688 + cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ 1689 + BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg 1690 + MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 1691 + BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 1692 + LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz 1693 + +uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm 1694 + hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn 1695 + 5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W 1696 + JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL 1697 + DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC 1698 + huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw 1699 + HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB 1700 + AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB 1701 + zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN 1702 + kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD 1703 + AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH 1704 + SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G 1705 + spki4cErx5z481+oghLrGREt 1706 + -----END CERTIFICATE----- 1707 + 1708 + -----BEGIN CERTIFICATE----- 1709 + MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW 1710 + MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy 1711 + c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE 1712 + BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 1713 + IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV 1714 + VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 1715 + cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT 1716 + QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh 1717 + F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v 1718 + c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w 1719 + mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd 1720 + VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX 1721 + teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ 1722 + f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe 1723 + Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ 1724 + nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB 1725 + /wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY 1726 + MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG 1727 + 9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc 1728 + aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX 1729 + IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn 1730 + ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z 1731 + uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN 1732 + Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja 1733 + QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW 1734 + koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 1735 + ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt 1736 + DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm 1737 + bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= 1738 + -----END CERTIFICATE----- 1739 + 1740 + -----BEGIN CERTIFICATE----- 1741 + MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW 1742 + MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy 1743 + c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD 1744 + VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 1745 + c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC 1746 + AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 1747 + WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG 1748 + FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq 1749 + XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL 1750 + se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb 1751 + KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd 1752 + IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 1753 + y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt 1754 + hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc 1755 + QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 1756 + Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV 1757 + HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV 1758 + HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ 1759 + KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z 1760 + dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ 1761 + L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr 1762 + Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo 1763 + ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY 1764 + T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz 1765 + GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m 1766 + 1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV 1767 + OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH 1768 + 6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX 1769 + QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS 1770 + -----END CERTIFICATE----- 1771 + 1772 + -----BEGIN CERTIFICATE----- 1773 + MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD 1774 + VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 1775 + IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 1776 + MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD 1777 + aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx 1778 + MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy 1779 + cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG 1780 + A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl 1781 + BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI 1782 + hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed 1783 + KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 1784 + G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 1785 + zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 1786 + ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG 1787 + HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 1788 + Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V 1789 + yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e 1790 + beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r 1791 + 6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh 1792 + wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog 1793 + zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW 1794 + BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr 1795 + ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp 1796 + ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk 1797 + cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt 1798 + YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC 1799 + CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow 1800 + KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI 1801 + hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ 1802 + UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz 1803 + X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x 1804 + fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz 1805 + a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd 1806 + Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd 1807 + SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O 1808 + AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso 1809 + M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge 1810 + v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z 1811 + 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B 1812 + -----END CERTIFICATE----- 1813 + 1814 + -----BEGIN CERTIFICATE----- 1815 + MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG 1816 + A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv 1817 + b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw 1818 + MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i 1819 + YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT 1820 + aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ 1821 + jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp 1822 + xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 1823 + 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG 1824 + snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ 1825 + U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 1826 + 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E 1827 + BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B 1828 + AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz 1829 + yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 1830 + 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP 1831 + AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad 1832 + DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME 1833 + HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== 1834 + -----END CERTIFICATE----- 1835 + 1836 + -----BEGIN CERTIFICATE----- 1837 + MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G 1838 + A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp 1839 + Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 1840 + MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG 1841 + A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI 1842 + hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL 1843 + v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 1844 + eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq 1845 + tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd 1846 + C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa 1847 + zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB 1848 + mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH 1849 + V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n 1850 + bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG 1851 + 3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs 1852 + J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO 1853 + 291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS 1854 + ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd 1855 + AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 1856 + TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== 1857 + -----END CERTIFICATE----- 1858 + 1859 + -----BEGIN CERTIFICATE----- 1860 + MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G 1861 + A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp 1862 + Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 1863 + MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG 1864 + A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI 1865 + hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 1866 + RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT 1867 + gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm 1868 + KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd 1869 + QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ 1870 + XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw 1871 + DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o 1872 + LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU 1873 + RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp 1874 + jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK 1875 + 6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX 1876 + mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs 1877 + Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH 1878 + WD9f 1879 + -----END CERTIFICATE----- 1880 + 1881 + -----BEGIN CERTIFICATE----- 1882 + MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh 1883 + MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE 1884 + YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 1885 + MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo 1886 + ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg 1887 + MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN 1888 + ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA 1889 + PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w 1890 + wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi 1891 + EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY 1892 + avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ 1893 + YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE 1894 + sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h 1895 + /t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 1896 + IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj 1897 + YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD 1898 + ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy 1899 + OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P 1900 + TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ 1901 + HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER 1902 + dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf 1903 + ReYNnyicsbkqWletNw+vHX/bvZ8= 1904 + -----END CERTIFICATE----- 1905 + 1906 + -----BEGIN CERTIFICATE----- 1907 + MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx 1908 + EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT 1909 + EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp 1910 + ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz 1911 + NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH 1912 + EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE 1913 + AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw 1914 + DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD 1915 + E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH 1916 + /PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy 1917 + DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh 1918 + GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR 1919 + tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA 1920 + AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE 1921 + FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX 1922 + WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu 1923 + 9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr 1924 + gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo 1925 + 2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO 1926 + LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI 1927 + 4uJEvlz36hz1 1928 + -----END CERTIFICATE----- 1929 + 1930 + -----BEGIN CERTIFICATE----- 1931 + MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD 1932 + VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv 1933 + bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv 1934 + b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV 1935 + UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU 1936 + cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds 1937 + b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH 1938 + iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS 1939 + r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 1940 + 04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r 1941 + GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 1942 + 3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P 1943 + lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ 1944 + -----END CERTIFICATE----- 1945 + 1946 + -----BEGIN CERTIFICATE----- 1947 + MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix 1948 + RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 1949 + dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p 1950 + YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw 1951 + NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK 1952 + EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl 1953 + cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl 1954 + c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB 1955 + BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz 1956 + dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ 1957 + fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns 1958 + bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD 1959 + 75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP 1960 + FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV 1961 + HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp 1962 + 5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu 1963 + b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA 1964 + A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p 1965 + 6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 1966 + TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 1967 + dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys 1968 + Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI 1969 + l7WdmplNsDz4SgCbZN2fOUvRJ9e4 1970 + -----END CERTIFICATE----- 1971 + 1972 + -----BEGIN CERTIFICATE----- 1973 + MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx 1974 + FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg 1975 + Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG 1976 + A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr 1977 + b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC 1978 + AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ 1979 + jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn 1980 + PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh 1981 + ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 1982 + nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h 1983 + q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED 1984 + MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC 1985 + mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 1986 + 7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB 1987 + oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs 1988 + EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO 1989 + fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi 1990 + AmvZWg== 1991 + -----END CERTIFICATE----- 1992 + 1993 + -----BEGIN CERTIFICATE----- 1994 + MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT 1995 + AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ 1996 + TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG 1997 + 9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw 1998 + MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM 1999 + BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO 2000 + MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2 2001 + LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI 2002 + s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2 2003 + xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4 2004 + u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b 2005 + F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx 2006 + Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd 2007 + PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV 2008 + HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx 2009 + NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF 2010 + AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ 2011 + L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY 2012 + YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg 2013 + Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a 2014 + NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R 2015 + 0982gaEbeC9xs/FZTEYYKKuF0mBWWg== 2016 + -----END CERTIFICATE----- 2017 + 2018 + -----BEGIN CERTIFICATE----- 2019 + MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 2020 + MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 2021 + ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD 2022 + VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j 2023 + b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq 2024 + scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO 2025 + xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H 2026 + LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX 2027 + uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD 2028 + yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ 2029 + JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q 2030 + rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN 2031 + BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L 2032 + hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB 2033 + QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ 2034 + HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu 2035 + Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg 2036 + QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB 2037 + BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx 2038 + MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC 2039 + AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA 2040 + A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb 2041 + laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 2042 + awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo 2043 + JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw 2044 + LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT 2045 + VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk 2046 + LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb 2047 + UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ 2048 + QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ 2049 + naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls 2050 + QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== 2051 + -----END CERTIFICATE----- 2052 + 2053 + -----BEGIN CERTIFICATE----- 2054 + MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN 2055 + AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp 2056 + dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw 2057 + MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw 2058 + CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ 2059 + MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB 2060 + AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB 2061 + SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz 2062 + ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH 2063 + LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP 2064 + PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL 2065 + 2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w 2066 + ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC 2067 + MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk 2068 + AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0 2069 + AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz 2070 + AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz 2071 + AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f 2072 + BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE 2073 + FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY 2074 + P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi 2075 + CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g 2076 + kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95 2077 + HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS 2078 + na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q 2079 + qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z 2080 + TbvGRNs2yyqcjg== 2081 + -----END CERTIFICATE----- 2082 + 2083 + -----BEGIN CERTIFICATE----- 2084 + MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAw 2085 + cjELMAkGA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNy 2086 + b3NlYyBMdGQuMRQwEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9z 2087 + ZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4 2088 + NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMN 2089 + TWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMTGU1p 2090 + Y3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 2091 + ggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2u 2092 + uO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+ 2093 + LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabA 2094 + vjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770 2095 + Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx 2096 + 62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcB 2097 + AQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3Aw 2098 + LQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAP 2099 + BgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIB 2100 + AQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1L1NaU1ov 2101 + MIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5 2102 + ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn 2103 + AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABT 2104 + AHoAbwBsAGcA4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABh 2105 + ACAAcwB6AGUAcgBpAG4AdAAgAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABo 2106 + AHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBa 2107 + AFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6Ly93d3cuZS1zemln 2108 + bm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NOPU1p 2109 + Y3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxP 2110 + PU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv 2111 + Y2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuB 2112 + EGluZm9AZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWdu 2113 + w7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWlj 2114 + cm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNV 2115 + HSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJI 2116 + VTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDAS 2117 + BgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBS 2118 + b290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS 2119 + 8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds 2120 + ZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl 2121 + 7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a 2122 + 86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfR 2123 + hUZLphK3dehKyVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/ 2124 + MPMMNz7UwiiAc7EBt51alhQBS6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= 2125 + -----END CERTIFICATE----- 2126 + 2127 + -----BEGIN CERTIFICATE----- 2128 + MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD 2129 + VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 2130 + ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G 2131 + CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y 2132 + OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx 2133 + FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp 2134 + Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o 2135 + dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP 2136 + kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc 2137 + cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U 2138 + fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 2139 + N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC 2140 + xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 2141 + +rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G 2142 + A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM 2143 + Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG 2144 + SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h 2145 + mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk 2146 + ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 2147 + tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c 2148 + 2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t 2149 + HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW 2150 + -----END CERTIFICATE----- 2151 + 2152 + -----BEGIN CERTIFICATE----- 2153 + MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG 2154 + EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 2155 + MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl 2156 + cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR 2157 + dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB 2158 + pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM 2159 + b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm 2160 + aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz 2161 + IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 2162 + MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT 2163 + lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz 2164 + AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 2165 + VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG 2166 + ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 2167 + BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG 2168 + AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M 2169 + U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh 2170 + bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C 2171 + +C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC 2172 + bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F 2173 + uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 2174 + XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= 2175 + -----END CERTIFICATE----- 2176 + 2177 + -----BEGIN CERTIFICATE----- 2178 + MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx 2179 + ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 2180 + b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD 2181 + EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 2182 + OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G 2183 + A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh 2184 + Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l 2185 + dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG 2186 + SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK 2187 + gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX 2188 + iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc 2189 + Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E 2190 + BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G 2191 + SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu 2192 + b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh 2193 + bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv 2194 + Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln 2195 + aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 2196 + IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh 2197 + c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph 2198 + biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo 2199 + ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP 2200 + UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj 2201 + YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo 2202 + dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA 2203 + bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 2204 + sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa 2205 + n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS 2206 + NitjrFgBazMpUIaD8QFI 2207 + -----END CERTIFICATE----- 2208 + 2209 + -----BEGIN CERTIFICATE----- 2210 + MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx 2211 + ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 2212 + b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD 2213 + EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X 2214 + DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw 2215 + DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u 2216 + c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr 2217 + TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN 2218 + BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA 2219 + OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC 2220 + 2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW 2221 + RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P 2222 + AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW 2223 + ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 2224 + YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz 2225 + b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO 2226 + ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB 2227 + IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs 2228 + b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs 2229 + ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s 2230 + YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg 2231 + a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g 2232 + SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 2233 + aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg 2234 + YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg 2235 + Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY 2236 + ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g 2237 + pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 2238 + Fp1hBWeAyNDYpQcCNJgEjTME1A== 2239 + -----END CERTIFICATE----- 2240 + 2241 + -----BEGIN CERTIFICATE----- 2242 + MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV 2243 + MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe 2244 + TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 2245 + dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB 2246 + KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 2247 + N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC 2248 + dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu 2249 + MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL 2250 + b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG 2251 + 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD 2252 + zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi 2253 + 3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 2254 + WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY 2255 + Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi 2256 + NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC 2257 + ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 2258 + QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 2259 + YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz 2260 + aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu 2261 + IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm 2262 + ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg 2263 + ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs 2264 + amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv 2265 + IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 2266 + Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 2267 + ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 2268 + YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg 2269 + dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs 2270 + b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G 2271 + CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO 2272 + xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP 2273 + 0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ 2274 + QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk 2275 + f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK 2276 + 8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI 2277 + -----END CERTIFICATE----- 2278 + 2279 + -----BEGIN CERTIFICATE----- 2280 + MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx 2281 + ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 2282 + b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQD 2283 + EzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVneXpvaSAoQ2xhc3MgUUEpIFRhbnVz 2284 + aXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0bG9jay5odTAeFw0w 2285 + MzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTERMA8G 2286 + A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh 2287 + Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5l 2288 + dExvY2sgTWlub3NpdGV0dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZh 2289 + bnlraWFkbzEeMBwGCSqGSIb3DQEJARYPaW5mb0BuZXRsb2NrLmh1MIIBIjANBgkq 2290 + hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRVCacbvWy5FPSKAtt2/Goq 2291 + eKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e8ia6AFQe 2292 + r7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO5 2293 + 3Lhbm+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWd 2294 + vLrqOU+L73Sa58XQ0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0l 2295 + mT+1fMptsK6ZmfoIYOcZwvK9UdPM0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4IC 2296 + wDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwggJ1Bglg 2297 + hkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2YW55IGEgTmV0 2298 + TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh 2299 + biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQg 2300 + ZWxla3Ryb25pa3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywg 2301 + dmFsYW1pbnQgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6 2302 + b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwgYXogQWx0YWxhbm9zIFN6ZXJ6b2Rl 2303 + c2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kgZWxqYXJhcyBtZWd0 2304 + ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczovL3d3 2305 + dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0Bu 2306 + ZXRsb2NrLm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBh 2307 + bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRo 2308 + ZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3 2309 + Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0IGluZm9AbmV0bG9jay5u 2310 + ZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3DQEBBQUA 2311 + A4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQ 2312 + MznNwNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+ 2313 + NFAwLvt/MpqNPfMgW/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCR 2314 + VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY 2315 + 83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR5qq5aKrN9p2QdRLqOBrKROi3 2316 + macqaJVmlaut74nLYKkGEsaUR+ko 2317 + -----END CERTIFICATE----- 2318 + 2319 + -----BEGIN CERTIFICATE----- 2320 + MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi 2321 + MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu 2322 + MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp 2323 + dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV 2324 + UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO 2325 + ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG 2326 + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz 2327 + c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP 2328 + OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl 2329 + mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF 2330 + BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 2331 + qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw 2332 + gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB 2333 + BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu 2334 + bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp 2335 + dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 2336 + 6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ 2337 + h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH 2338 + /nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv 2339 + wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN 2340 + pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey 2341 + -----END CERTIFICATE----- 2342 + 2343 + -----BEGIN CERTIFICATE----- 2344 + MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB 2345 + ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly 2346 + aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl 2347 + ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w 2348 + NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G 2349 + A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD 2350 + VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX 2351 + SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 2352 + MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR 2353 + VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 2354 + w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF 2355 + mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg 2356 + 4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 2357 + 4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw 2358 + DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw 2359 + EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx 2360 + SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 2361 + ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 2362 + vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa 2363 + hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi 2364 + Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ 2365 + /L7fCg0= 2366 + -----END CERTIFICATE----- 2367 + 2368 + -----BEGIN CERTIFICATE----- 2369 + MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC 2370 + TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 2371 + aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 2372 + aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz 2373 + MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw 2374 + IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR 2375 + dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG 2376 + 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp 2377 + li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D 2378 + rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ 2379 + WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug 2380 + F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU 2381 + xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC 2382 + Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv 2383 + dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw 2384 + ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl 2385 + IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh 2386 + c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy 2387 + ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh 2388 + Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI 2389 + KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T 2390 + KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq 2391 + y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p 2392 + dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD 2393 + VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL 2394 + MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk 2395 + fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 2396 + 7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R 2397 + cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y 2398 + mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW 2399 + xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK 2400 + SnQ2+Q== 2401 + -----END CERTIFICATE----- 2402 + 2403 + -----BEGIN CERTIFICATE----- 2404 + MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x 2405 + GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv 2406 + b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV 2407 + BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W 2408 + YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa 2409 + GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg 2410 + Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J 2411 + WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB 2412 + rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp 2413 + +ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 2414 + ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i 2415 + Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz 2416 + PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og 2417 + /zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH 2418 + oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI 2419 + yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud 2420 + EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 2421 + A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL 2422 + MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT 2423 + ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f 2424 + BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn 2425 + g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl 2426 + fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K 2427 + WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha 2428 + B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc 2429 + hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR 2430 + TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD 2431 + mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z 2432 + ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y 2433 + 4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza 2434 + 8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u 2435 + -----END CERTIFICATE----- 2436 + 2437 + -----BEGIN CERTIFICATE----- 2438 + MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x 2439 + GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv 2440 + b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV 2441 + BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W 2442 + YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM 2443 + V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB 2444 + 4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr 2445 + H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd 2446 + 8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv 2447 + vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT 2448 + mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe 2449 + btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc 2450 + T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt 2451 + WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ 2452 + c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A 2453 + 4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD 2454 + VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG 2455 + CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 2456 + aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 2457 + aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu 2458 + dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw 2459 + czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G 2460 + A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC 2461 + TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg 2462 + Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 2463 + 7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem 2464 + d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd 2465 + +LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B 2466 + 4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN 2467 + t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x 2468 + DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 2469 + k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s 2470 + zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j 2471 + Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT 2472 + mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK 2473 + 4SVhM7JZG+Ju1zdXtg2pEto= 2474 + -----END CERTIFICATE----- 2475 + 2476 + -----BEGIN CERTIFICATE----- 2477 + MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJF 2478 + UzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJ 2479 + R1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcN 2480 + MDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3WjBoMQswCQYDVQQGEwJFUzEfMB0G 2481 + A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScw 2482 + JQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0GCSqG 2483 + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+ 2484 + WmmmO3I2F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKj 2485 + SgbwJ/BXufjpTjJ3Cj9BZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGl 2486 + u6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQD0EbtFpKd71ng+CT516nDOeB0/RSrFOy 2487 + A8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXteJajCq+TA81yc477OMUxk 2488 + Hl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMBAAGjggM7 2489 + MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBr 2490 + aS5ndmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIIC 2491 + IwYKKwYBBAG/VQIBADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8A 2492 + cgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIA 2493 + YQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIAYQBsAGkAdABhAHQAIABWAGEA 2494 + bABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQByAGEAYwBpAPMA 2495 + bgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA 2496 + aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMA 2497 + aQBvAG4AYQBtAGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQA 2498 + ZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA 2499 + YwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBuAHQAcgBhACAAZQBuACAAbABhACAA 2500 + ZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAAOgAvAC8AdwB3AHcA 2501 + LgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0dHA6 2502 + Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+y 2503 + eAT8MIGVBgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQsw 2504 + CQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0G 2505 + A1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVu 2506 + Y2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRhTvW1yEICKrNcda3Fbcrn 2507 + lD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdzCkj+IHLt 2508 + b8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg 2509 + 9J63NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XF 2510 + ducTZnV+ZfsBn5OHiJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmC 2511 + IoaZM3Fa6hlXPZHNqcCjbgcTpsnt+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= 2512 + -----END CERTIFICATE----- 2513 + 2514 + -----BEGIN CERTIFICATE----- 2515 + MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 2516 + IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz 2517 + BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y 2518 + aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG 2519 + 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy 2520 + NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y 2521 + azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs 2522 + YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw 2523 + Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl 2524 + cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD 2525 + cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs 2526 + 2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY 2527 + JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE 2528 + Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ 2529 + n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A 2530 + PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu 2531 + -----END CERTIFICATE----- 2532 + 2533 + -----BEGIN CERTIFICATE----- 2534 + MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 2535 + MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp 2536 + dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX 2537 + BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy 2538 + MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp 2539 + eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg 2540 + /9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl 2541 + wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh 2542 + AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 2543 + PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu 2544 + AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB 2545 + BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR 2546 + MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc 2547 + HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ 2548 + Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ 2549 + f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO 2550 + rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch 2551 + 6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 2552 + 7CAFYd4= 2553 + -----END CERTIFICATE----- 2554 + 2555 + -----BEGIN CERTIFICATE----- 2556 + MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCB 2557 + rjELMAkGA1UEBhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcp 2558 + MRIwEAYDVQQHEwlTdHV0dGdhcnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fz 2559 + c2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVTLVRSVVNUIEF1dGhlbnRpY2F0aW9u 2560 + IGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0wNTA2MjIwMDAwMDBa 2561 + Fw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFkZW4t 2562 + V3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMg 2563 + RGV1dHNjaGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJV 2564 + U1QgQXV0aGVudGljYXRpb24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBO 2565 + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1 2566 + toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob4QSwI7+Vio5bG0F/WsPo 2567 + TUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXLg3KSwlOy 2568 + ggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1 2569 + XgqfeN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteF 2570 + hy+S8dF2g08LOlk3KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm 2571 + 7QIDAQABo4GSMIGPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEG 2572 + MCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJvbmxpbmUxLTIwNDgtNTAdBgNV 2573 + HQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAUD8oeXHngovMp 2574 + ttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD 2575 + pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFo 2576 + LtU96G7m1R08P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersF 2577 + iXOMy6ZNwPv2AtawB6MDwidAnwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0y 2578 + h9WUUpY6RsZxlj33mA6ykaqP2vROJAA5VeitF7nTNCtKqUDMFypVZUF0Qn71wK/I 2579 + k63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8bHz2eBIPdltkdOpQ= 2580 + -----END CERTIFICATE----- 2581 + 2582 + -----BEGIN CERTIFICATE----- 2583 + MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK 2584 + MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x 2585 + GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx 2586 + MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg 2587 + Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG 2588 + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ 2589 + iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa 2590 + /FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ 2591 + jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI 2592 + HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 2593 + sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w 2594 + gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF 2595 + MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw 2596 + KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG 2597 + AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L 2598 + URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO 2599 + H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm 2600 + I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY 2601 + iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc 2602 + f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW 2603 + -----END CERTIFICATE----- 2604 + 2605 + -----BEGIN CERTIFICATE----- 2606 + MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr 2607 + MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG 2608 + A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 2609 + MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp 2610 + Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD 2611 + QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz 2612 + i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 2613 + h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV 2614 + MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 2615 + UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni 2616 + 8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC 2617 + h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD 2618 + VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB 2619 + AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm 2620 + KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ 2621 + X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr 2622 + QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 2623 + pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN 2624 + QSdJQO7e5iNEOdyhIta6A/I= 2625 + -----END CERTIFICATE----- 2626 + 2627 + -----BEGIN CERTIFICATE----- 2628 + MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI 2629 + MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x 2630 + FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz 2631 + MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv 2632 + cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN 2633 + AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz 2634 + Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO 2635 + 0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao 2636 + wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj 2637 + 7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS 2638 + 8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT 2639 + BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB 2640 + /zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg 2641 + JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC 2642 + NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 2643 + 6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ 2644 + 3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm 2645 + D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS 2646 + CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 2647 + 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= 2648 + -----END CERTIFICATE----- 2649 + 2650 + -----BEGIN CERTIFICATE----- 2651 + MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl 2652 + MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh 2653 + U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz 2654 + MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N 2655 + IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 2656 + bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 2657 + ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE 2658 + RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO 2659 + zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 2660 + bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF 2661 + MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 2662 + VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC 2663 + OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G 2664 + CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW 2665 + tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ 2666 + q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb 2667 + EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ 2668 + Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O 2669 + VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 2670 + -----END CERTIFICATE----- 2671 + 2672 + -----BEGIN CERTIFICATE----- 2673 + MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY 2674 + MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t 2675 + dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 2676 + WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD 2677 + VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 2678 + DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 2679 + 9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ 2680 + DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 2681 + Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N 2682 + QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ 2683 + xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G 2684 + A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T 2685 + AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG 2686 + kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr 2687 + Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 2688 + Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU 2689 + JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot 2690 + RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== 2691 + -----END CERTIFICATE----- 2692 + 2693 + -----BEGIN CERTIFICATE----- 2694 + MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl 2695 + MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe 2696 + U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX 2697 + DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy 2698 + dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj 2699 + YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV 2700 + OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr 2701 + zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM 2702 + VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ 2703 + hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO 2704 + ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw 2705 + awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs 2706 + OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 2707 + DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF 2708 + coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc 2709 + okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 2710 + t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy 2711 + 1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ 2712 + SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 2713 + -----END CERTIFICATE----- 2714 + 2715 + -----BEGIN CERTIFICATE----- 2716 + MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP 2717 + MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx 2718 + MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV 2719 + BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI 2720 + hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG 2721 + 29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk 2722 + oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk 2723 + 3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL 2724 + qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN 2725 + nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw 2726 + DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG 2727 + MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX 2728 + ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H 2729 + DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO 2730 + TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv 2731 + kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w 2732 + zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa 2733 + -----END CERTIFICATE----- 2734 + 2735 + -----BEGIN CERTIFICATE----- 2736 + MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP 2737 + MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx 2738 + MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV 2739 + BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI 2740 + hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o 2741 + Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt 2742 + 5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s 2743 + 3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej 2744 + vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu 2745 + 8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw 2746 + DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG 2747 + MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil 2748 + zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ 2749 + 3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD 2750 + FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 2751 + Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 2752 + ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M 2753 + -----END CERTIFICATE----- 2754 + 2755 + -----BEGIN CERTIFICATE----- 2756 + MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO 2757 + TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh 2758 + dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy 2759 + MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk 2760 + ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB 2761 + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn 2762 + ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 2763 + 9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO 2764 + hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U 2765 + tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o 2766 + BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh 2767 + SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww 2768 + OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv 2769 + cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA 2770 + 7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k 2771 + /rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm 2772 + eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 2773 + u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy 2774 + 7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR 2775 + iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== 2776 + -----END CERTIFICATE----- 2777 + 2778 + -----BEGIN CERTIFICATE----- 2779 + MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO 2780 + TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh 2781 + dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX 2782 + DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl 2783 + ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv 2784 + b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 2785 + qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp 2786 + uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU 2787 + Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE 2788 + pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp 2789 + 5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M 2790 + UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN 2791 + GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy 2792 + 5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv 2793 + 6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK 2794 + eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 2795 + B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ 2796 + BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov 2797 + L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV 2798 + HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG 2799 + SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS 2800 + CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen 2801 + 5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 2802 + IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK 2803 + gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL 2804 + +63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL 2805 + vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm 2806 + bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk 2807 + N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC 2808 + Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z 2809 + ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== 2810 + -----END CERTIFICATE----- 2811 + 2812 + -----BEGIN CERTIFICATE----- 2813 + MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl 2814 + MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp 2815 + U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw 2816 + NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE 2817 + ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp 2818 + ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 2819 + DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf 2820 + 8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN 2821 + +lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 2822 + X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa 2823 + K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA 2824 + 1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G 2825 + A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR 2826 + zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 2827 + YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD 2828 + bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w 2829 + DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 2830 + L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D 2831 + eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl 2832 + xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp 2833 + VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY 2834 + WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= 2835 + -----END CERTIFICATE----- 2836 + 2837 + -----BEGIN CERTIFICATE----- 2838 + MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx 2839 + EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT 2840 + HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs 2841 + ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw 2842 + MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 2843 + b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj 2844 + aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp 2845 + Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 2846 + ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg 2847 + nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 2848 + HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N 2849 + Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN 2850 + dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 2851 + HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO 2852 + BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G 2853 + CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU 2854 + sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 2855 + 4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg 2856 + 8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K 2857 + pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 2858 + mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 2859 + -----END CERTIFICATE----- 2860 + 2861 + -----BEGIN CERTIFICATE----- 2862 + MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx 2863 + EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT 2864 + HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs 2865 + ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 2866 + MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD 2867 + VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy 2868 + ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy 2869 + dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI 2870 + hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p 2871 + OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 2872 + 8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K 2873 + Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe 2874 + hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk 2875 + 6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw 2876 + DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q 2877 + AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI 2878 + bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB 2879 + ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z 2880 + qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd 2881 + iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn 2882 + 0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN 2883 + sSi6 2884 + -----END CERTIFICATE----- 2885 + 2886 + -----BEGIN CERTIFICATE----- 2887 + MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW 2888 + MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg 2889 + Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh 2890 + dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 2891 + MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi 2892 + U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh 2893 + cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA 2894 + A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk 2895 + pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf 2896 + OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C 2897 + Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT 2898 + Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi 2899 + HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM 2900 + Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w 2901 + +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ 2902 + Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 2903 + Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B 2904 + 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID 2905 + AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE 2906 + FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j 2907 + ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js 2908 + LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM 2909 + BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 2910 + Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy 2911 + dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh 2912 + cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh 2913 + YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg 2914 + dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp 2915 + bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ 2916 + YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT 2917 + TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ 2918 + 9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 2919 + jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW 2920 + FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz 2921 + ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 2922 + ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L 2923 + EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu 2924 + L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq 2925 + yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC 2926 + O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V 2927 + um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh 2928 + NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= 2929 + -----END CERTIFICATE----- 2930 + 2931 + -----BEGIN CERTIFICATE----- 2932 + MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW 2933 + MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg 2934 + Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh 2935 + dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 2936 + MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi 2937 + U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh 2938 + cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA 2939 + A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk 2940 + pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf 2941 + OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C 2942 + Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT 2943 + Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi 2944 + HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM 2945 + Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w 2946 + +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ 2947 + Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 2948 + Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B 2949 + 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID 2950 + AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD 2951 + VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul 2952 + F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC 2953 + ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w 2954 + ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk 2955 + aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 2956 + YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg 2957 + c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 2958 + aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 2959 + d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG 2960 + CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 2961 + dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF 2962 + wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS 2963 + Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst 2964 + 0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc 2965 + pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl 2966 + CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF 2967 + P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK 2968 + 1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm 2969 + KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE 2970 + JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ 2971 + 8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm 2972 + fyWl8kgAwKQB2j8= 2973 + -----END CERTIFICATE----- 2974 + 2975 + -----BEGIN CERTIFICATE----- 2976 + MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW 2977 + MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm 2978 + aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 2979 + OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG 2980 + A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G 2981 + CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ 2982 + JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD 2983 + vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo 2984 + D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ 2985 + Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW 2986 + RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK 2987 + HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN 2988 + nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM 2989 + 0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i 2990 + UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 2991 + Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg 2992 + TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 2993 + AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL 2994 + BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K 2995 + 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX 2996 + UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl 2997 + 6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK 2998 + 9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ 2999 + HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI 3000 + wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY 3001 + XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l 3002 + IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo 3003 + hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr 3004 + so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI 3005 + -----END CERTIFICATE----- 3006 + 3007 + -----BEGIN CERTIFICATE----- 3008 + MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk 3009 + MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 3010 + YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg 3011 + Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT 3012 + AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp 3013 + Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN 3014 + BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 3015 + m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih 3016 + FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ 3017 + TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F 3018 + EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco 3019 + kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu 3020 + HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF 3021 + vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo 3022 + 19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC 3023 + L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW 3024 + bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX 3025 + JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw 3026 + FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j 3027 + BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc 3028 + K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf 3029 + ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik 3030 + Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB 3031 + sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e 3032 + 3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR 3033 + ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip 3034 + mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH 3035 + b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf 3036 + rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms 3037 + hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y 3038 + zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 3039 + MBr1mmz0DlP5OlvRHA== 3040 + -----END CERTIFICATE----- 3041 + 3042 + -----BEGIN CERTIFICATE----- 3043 + MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 3044 + BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln 3045 + biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF 3046 + MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT 3047 + d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 3048 + CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 3049 + 76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ 3050 + bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c 3051 + 6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE 3052 + emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd 3053 + MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt 3054 + MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y 3055 + MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y 3056 + FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi 3057 + aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM 3058 + gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB 3059 + qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 3060 + lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn 3061 + 8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov 3062 + L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 3063 + 45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO 3064 + UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 3065 + O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC 3066 + bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv 3067 + GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a 3068 + 77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC 3069 + hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 3070 + 92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp 3071 + Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w 3072 + ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt 3073 + Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ 3074 + -----END CERTIFICATE----- 3075 + 3076 + -----BEGIN CERTIFICATE----- 3077 + MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE 3078 + BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu 3079 + IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw 3080 + WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD 3081 + ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD 3082 + ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y 3083 + IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn 3084 + IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ 3085 + 6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob 3086 + jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw 3087 + izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl 3088 + +zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY 3089 + zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP 3090 + pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF 3091 + KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW 3092 + ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB 3093 + AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O 3094 + BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 3095 + ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW 3096 + IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA 3097 + A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 3098 + uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ 3099 + FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 3100 + jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ 3101 + u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D 3102 + YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 3103 + puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa 3104 + icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG 3105 + DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x 3106 + kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z 3107 + Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== 3108 + -----END CERTIFICATE----- 3109 + 3110 + -----BEGIN CERTIFICATE----- 3111 + MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE 3112 + BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu 3113 + IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow 3114 + RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY 3115 + U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A 3116 + MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv 3117 + Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br 3118 + YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF 3119 + nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH 3120 + 6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt 3121 + eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ 3122 + c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ 3123 + MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH 3124 + HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf 3125 + jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 3126 + 5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB 3127 + rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU 3128 + F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c 3129 + wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 3130 + cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB 3131 + AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp 3132 + WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 3133 + xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ 3134 + 2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ 3135 + IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 3136 + aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X 3137 + em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR 3138 + dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ 3139 + OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ 3140 + hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy 3141 + tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u 3142 + -----END CERTIFICATE----- 3143 + 3144 + -----BEGIN CERTIFICATE----- 3145 + MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx 3146 + KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd 3147 + BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl 3148 + YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 3149 + OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy 3150 + aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 3151 + ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G 3152 + CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN 3153 + 8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ 3154 + RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 3155 + hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 3156 + ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM 3157 + EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj 3158 + QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 3159 + A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy 3160 + WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ 3161 + 1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 3162 + 6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT 3163 + 91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml 3164 + e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p 3165 + TpPDpFQUWw== 3166 + -----END CERTIFICATE----- 3167 + 3168 + -----BEGIN CERTIFICATE----- 3169 + MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ 3170 + MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj 3171 + YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow 3172 + PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp 3173 + Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB 3174 + AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR 3175 + IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q 3176 + gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy 3177 + yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts 3178 + F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 3179 + jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx 3180 + ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC 3181 + VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK 3182 + YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH 3183 + EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN 3184 + Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud 3185 + DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE 3186 + MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK 3187 + UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ 3188 + TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf 3189 + qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK 3190 + ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE 3191 + JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 3192 + hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 3193 + EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm 3194 + nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX 3195 + udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz 3196 + ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe 3197 + LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl 3198 + pYYsfPQS 3199 + -----END CERTIFICATE----- 3200 + 3201 + -----BEGIN CERTIFICATE----- 3202 + MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL 3203 + MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV 3204 + BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 3205 + Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 3206 + OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i 3207 + SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc 3208 + VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD 3209 + ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf 3210 + tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg 3211 + uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J 3212 + XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK 3213 + 8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 3214 + 5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud 3215 + EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 3216 + kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy 3217 + dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 3218 + Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz 3219 + JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 3220 + Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u 3221 + TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS 3222 + GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt 3223 + ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 3224 + au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV 3225 + hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI 3226 + dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== 3227 + -----END CERTIFICATE----- 3228 + 3229 + -----BEGIN CERTIFICATE----- 3230 + MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL 3231 + MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV 3232 + BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 3233 + Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 3234 + OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i 3235 + SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc 3236 + VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD 3237 + ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW 3238 + Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q 3239 + Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 3240 + 1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq 3241 + ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 3242 + Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud 3243 + EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX 3244 + XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy 3245 + dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 3246 + Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz 3247 + JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 3248 + Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u 3249 + TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN 3250 + irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 3251 + TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 3252 + g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB 3253 + 95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj 3254 + S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== 3255 + -----END CERTIFICATE----- 3256 + 3257 + -----BEGIN CERTIFICATE----- 3258 + MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL 3259 + MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV 3260 + BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 3261 + c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx 3262 + MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg 3263 + R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD 3264 + VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN 3265 + AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR 3266 + JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T 3267 + fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu 3268 + jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z 3269 + wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ 3270 + fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD 3271 + VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO 3272 + BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G 3273 + CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 3274 + 7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn 3275 + 8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs 3276 + ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT 3277 + ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ 3278 + 2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY 3279 + -----END CERTIFICATE----- 3280 + 3281 + -----BEGIN CERTIFICATE----- 3282 + MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL 3283 + MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV 3284 + BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1 3285 + c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy 3286 + MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl 3287 + ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm 3288 + BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG 3289 + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF 3290 + 5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv 3291 + DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v 3292 + zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT 3293 + yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj 3294 + dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh 3295 + MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB 3296 + Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI 3297 + 4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz 3298 + dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY 3299 + aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G 3300 + DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV 3301 + CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH 3302 + LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== 3303 + -----END CERTIFICATE----- 3304 + 3305 + -----BEGIN CERTIFICATE----- 3306 + MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE 3307 + SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg 3308 + Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV 3309 + BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl 3310 + cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA 3311 + vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu 3312 + Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a 3313 + 0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 3314 + 4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN 3315 + eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD 3316 + R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG 3317 + A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu 3318 + dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME 3319 + Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 3320 + WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw 3321 + HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ 3322 + KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO 3323 + Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX 3324 + wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ 3325 + 2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 3326 + 9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 3327 + jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 3328 + aQNiuJkFBT1reBK9sG9l 3329 + -----END CERTIFICATE----- 3330 + 3331 + -----BEGIN CERTIFICATE----- 3332 + MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE 3333 + SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw 3334 + ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU 3335 + REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 3336 + MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr 3337 + 2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s 3338 + 2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU 3339 + GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj 3340 + dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r 3341 + TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/ 3342 + BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB 3343 + AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv 3344 + c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl 3345 + ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu 3346 + MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg 3347 + T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud 3348 + HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD 3349 + VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny 3350 + bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy 3351 + MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ 3352 + J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG 3353 + SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom 3354 + JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO 3355 + inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y 3356 + caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB 3357 + mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ 3358 + YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9 3359 + BKNDLdr8C2LqL19iUw== 3360 + -----END CERTIFICATE----- 3361 + 3362 + -----BEGIN CERTIFICATE----- 3363 + MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx 3364 + FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD 3365 + VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv 3366 + biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy 3367 + dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t 3368 + MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB 3369 + MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG 3370 + A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp 3371 + b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl 3372 + cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv 3373 + bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE 3374 + VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ 3375 + ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR 3376 + uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG 3377 + 9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI 3378 + hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM 3379 + pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== 3380 + -----END CERTIFICATE----- 3381 + 3382 + -----BEGIN CERTIFICATE----- 3383 + MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB 3384 + qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf 3385 + Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw 3386 + MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV 3387 + BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw 3388 + NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j 3389 + LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG 3390 + A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl 3391 + IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG 3392 + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs 3393 + W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta 3394 + 3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk 3395 + 6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 3396 + Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J 3397 + NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA 3398 + MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP 3399 + r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU 3400 + DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz 3401 + YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX 3402 + xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 3403 + /qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ 3404 + LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 3405 + jVaMaA== 3406 + -----END CERTIFICATE----- 3407 + 3408 + -----BEGIN CERTIFICATE----- 3409 + MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL 3410 + MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp 3411 + IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi 3412 + BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw 3413 + MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh 3414 + d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig 3415 + YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v 3416 + dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ 3417 + BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 3418 + papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E 3419 + BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K 3420 + DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 3421 + KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox 3422 + XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== 3423 + -----END CERTIFICATE----- 3424 + 3425 + -----BEGIN CERTIFICATE----- 3426 + MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB 3427 + rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf 3428 + Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw 3429 + MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV 3430 + BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa 3431 + Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl 3432 + LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u 3433 + MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl 3434 + ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz 3435 + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm 3436 + gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 3437 + YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf 3438 + b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 3439 + 9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S 3440 + zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk 3441 + OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV 3442 + HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA 3443 + 2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW 3444 + oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu 3445 + t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c 3446 + KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM 3447 + m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu 3448 + MdRAGmI0Nj81Aa6sY6A= 3449 + -----END CERTIFICATE----- 3450 + 3451 + -----BEGIN CERTIFICATE----- 3452 + MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx 3453 + FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD 3454 + VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv 3455 + biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm 3456 + MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx 3457 + MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT 3458 + DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 3459 + dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl 3460 + cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 3461 + DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD 3462 + gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 3463 + yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX 3464 + L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj 3465 + EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG 3466 + 7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e 3467 + QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ 3468 + qdq5snUb9kLy78fyGPmJvKP/iiMucEc= 3469 + -----END CERTIFICATE----- 3470 + 3471 + -----BEGIN CERTIFICATE----- 3472 + MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF 3473 + MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL 3474 + ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx 3475 + MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc 3476 + MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD 3477 + ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ 3478 + AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH 3479 + iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj 3480 + vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA 3481 + 0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB 3482 + OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ 3483 + BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E 3484 + FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 3485 + GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW 3486 + zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 3487 + 1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE 3488 + f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F 3489 + jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN 3490 + ZetX2fNXlrtIzYE= 3491 + -----END CERTIFICATE----- 3492 + 3493 + -----BEGIN CERTIFICATE----- 3494 + MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc 3495 + UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx 3496 + c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg 3497 + MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 3498 + dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz 3499 + MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy 3500 + dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD 3501 + VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg 3502 + xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu 3503 + xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 3504 + XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k 3505 + heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J 3506 + YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C 3507 + urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 3508 + JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 3509 + b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV 3510 + 9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 3511 + kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh 3512 + fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy 3513 + B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA 3514 + aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS 3515 + RGQDJereW26fyfJOrN3H 3516 + -----END CERTIFICATE----- 3517 + 3518 + -----BEGIN CERTIFICATE----- 3519 + MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc 3520 + UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx 3521 + c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS 3522 + S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg 3523 + SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 3524 + WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv 3525 + bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU 3526 + UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw 3527 + bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe 3528 + LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 3529 + AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef 3530 + J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh 3531 + R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ 3532 + Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX 3533 + JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p 3534 + zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S 3535 + Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ 3536 + KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq 3537 + ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 3538 + Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz 3539 + gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH 3540 + uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS 3541 + y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= 3542 + -----END CERTIFICATE----- 3543 + 3544 + -----BEGIN CERTIFICATE----- 3545 + MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES 3546 + MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU 3547 + V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz 3548 + WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO 3549 + LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm 3550 + aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 3551 + AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE 3552 + AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH 3553 + K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX 3554 + RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z 3555 + rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx 3556 + 3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV 3557 + HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq 3558 + hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC 3559 + MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls 3560 + XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D 3561 + lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn 3562 + aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ 3563 + YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== 3564 + -----END CERTIFICATE----- 3565 + 3566 + -----BEGIN CERTIFICATE----- 3567 + MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRS 3568 + MRgwFgYDVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJp 3569 + bGltc2VsIHZlIFRla25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSw 3570 + VEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFy 3571 + YcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNVBAsMGkthbXUgU2Vy 3572 + dGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUgS8O2 3573 + ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAe 3574 + Fw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIx 3575 + GDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls 3576 + aW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBU 3577 + QUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJh 3578 + xZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0 3579 + aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7Zr 3580 + IFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIB 3581 + IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4h 3582 + gb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yK 3583 + O7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+818qEhTsXO 3584 + fJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw 3585 + lZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL 3586 + hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQID 3587 + AQABo0IwQDAdBgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/ 3588 + BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmP 3589 + NOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7t 3590 + wyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLTy9LQQfMmNkqblWwM 3591 + 7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYhLBOh 3592 + gLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5n 3593 + oN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs 3594 + yZyQ2uypQjyttgI= 3595 + -----END CERTIFICATE----- 3596 + 3597 + -----BEGIN CERTIFICATE----- 3598 + MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB 3599 + kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug 3600 + Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho 3601 + dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw 3602 + IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG 3603 + EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD 3604 + VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu 3605 + dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN 3606 + BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 3607 + E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ 3608 + D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK 3609 + 4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq 3610 + lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW 3611 + bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB 3612 + o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT 3613 + MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js 3614 + LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr 3615 + BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB 3616 + AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft 3617 + Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj 3618 + j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH 3619 + KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv 3620 + 2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 3621 + mfnGV/TJVTl4uix5yaaIK/QI 3622 + -----END CERTIFICATE----- 3623 + 3624 + -----BEGIN CERTIFICATE----- 3625 + MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB 3626 + rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug 3627 + Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho 3628 + dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt 3629 + Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa 3630 + Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV 3631 + BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l 3632 + dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE 3633 + AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls 3634 + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B 3635 + YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 3636 + hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l 3637 + L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm 3638 + SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM 3639 + 1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws 3640 + 6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud 3641 + DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw 3642 + Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 3643 + aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH 3644 + AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u 3645 + 7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 3646 + xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ 3647 + rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim 3648 + eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk 3649 + USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= 3650 + -----END CERTIFICATE----- 3651 + 3652 + -----BEGIN CERTIFICATE----- 3653 + MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB 3654 + lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug 3655 + Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho 3656 + dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt 3657 + SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG 3658 + A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe 3659 + MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v 3660 + d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh 3661 + cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn 3662 + 0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ 3663 + M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a 3664 + MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd 3665 + oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI 3666 + DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy 3667 + oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD 3668 + VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 3669 + dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy 3670 + bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF 3671 + BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM 3672 + //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli 3673 + CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE 3674 + CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t 3675 + 3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS 3676 + KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== 3677 + -----END CERTIFICATE----- 3678 + 3679 + -----BEGIN CERTIFICATE----- 3680 + MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB 3681 + lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug 3682 + Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho 3683 + dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt 3684 + T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV 3685 + BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc 3686 + BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3 3687 + dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC 3688 + ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP 3689 + HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO 3690 + KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo 3691 + 5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+ 3692 + pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb 3693 + kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC 3694 + AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E 3695 + FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov 3696 + L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV 3697 + HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN 3698 + AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw 3699 + NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB 3700 + mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU 3701 + 4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5 3702 + 81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR 3703 + Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= 3704 + -----END CERTIFICATE----- 3705 + 3706 + -----BEGIN CERTIFICATE----- 3707 + MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB 3708 + ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug 3709 + Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho 3710 + dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt 3711 + TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 3712 + NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 3713 + IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD 3714 + VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS 3715 + Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB 3716 + DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 3717 + N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH 3718 + iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe 3719 + YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 3720 + axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g 3721 + yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD 3722 + AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh 3723 + ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V 3724 + VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB 3725 + BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y 3726 + IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs 3727 + QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 3728 + ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM 3729 + YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb 3730 + QErNaLly7HF27FSOH4UMAWr6pjisH8SE 3731 + -----END CERTIFICATE----- 3732 + 3733 + -----BEGIN CERTIFICATE----- 3734 + MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 3735 + IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz 3736 + BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y 3737 + aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG 3738 + 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy 3739 + NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y 3740 + azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs 3741 + YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw 3742 + Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl 3743 + cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y 3744 + LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ 3745 + TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y 3746 + TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 3747 + LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW 3748 + I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw 3749 + nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI 3750 + -----END CERTIFICATE----- 3751 + 3752 + -----BEGIN CERTIFICATE----- 3753 + MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 3754 + IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz 3755 + BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y 3756 + aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG 3757 + 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy 3758 + NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y 3759 + azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs 3760 + YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw 3761 + Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl 3762 + cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY 3763 + dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 3764 + WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS 3765 + v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v 3766 + UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu 3767 + IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC 3768 + W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd 3769 + -----END CERTIFICATE----- 3770 + 3771 + -----BEGIN CERTIFICATE----- 3772 + MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG 3773 + A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz 3774 + cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 3775 + MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV 3776 + BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt 3777 + YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN 3778 + ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f 3779 + zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi 3780 + TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G 3781 + CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW 3782 + NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV 3783 + Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb 3784 + -----END CERTIFICATE----- 3785 + 3786 + -----BEGIN CERTIFICATE----- 3787 + MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ 3788 + BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh 3789 + c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy 3790 + MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp 3791 + emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X 3792 + DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw 3793 + FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg 3794 + UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo 3795 + YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 3796 + MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB 3797 + AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK 3798 + VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm 3799 + Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID 3800 + AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J 3801 + h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul 3802 + uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 3803 + DzFc6PLZ 3804 + -----END CERTIFICATE----- 3805 + 3806 + -----BEGIN CERTIFICATE----- 3807 + MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw 3808 + CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl 3809 + cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu 3810 + LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT 3811 + aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp 3812 + dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD 3813 + VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT 3814 + aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ 3815 + bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu 3816 + IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 3817 + LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 3818 + nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO 3819 + 8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV 3820 + ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb 3821 + PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 3822 + 6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr 3823 + n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a 3824 + qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 3825 + wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 3826 + ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs 3827 + pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 3828 + E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== 3829 + -----END CERTIFICATE----- 3830 + 3831 + -----BEGIN CERTIFICATE----- 3832 + MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw 3833 + CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns 3834 + YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH 3835 + MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y 3836 + aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe 3837 + Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX 3838 + MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj 3839 + IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx 3840 + KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s 3841 + eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B 3842 + AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM 3843 + HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw 3844 + DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC 3845 + AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji 3846 + nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX 3847 + rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn 3848 + jBJ7xUS0rg== 3849 + -----END CERTIFICATE----- 3850 + 3851 + -----BEGIN CERTIFICATE----- 3852 + MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ 3853 + BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy 3854 + aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s 3855 + IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp 3856 + Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 3857 + eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV 3858 + BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp 3859 + Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu 3860 + Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g 3861 + Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt 3862 + IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU 3863 + J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO 3864 + JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY 3865 + wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o 3866 + koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN 3867 + qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E 3868 + Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe 3869 + xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u 3870 + 7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU 3871 + sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI 3872 + sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP 3873 + cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q 3874 + -----END CERTIFICATE----- 3875 + 3876 + -----BEGIN CERTIFICATE----- 3877 + MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG 3878 + A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz 3879 + cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 3880 + MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV 3881 + BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt 3882 + YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN 3883 + ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE 3884 + BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is 3885 + I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G 3886 + CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i 3887 + 2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ 3888 + 2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ 3889 + -----END CERTIFICATE----- 3890 + 3891 + -----BEGIN CERTIFICATE----- 3892 + MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG 3893 + A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz 3894 + cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 3895 + MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV 3896 + BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt 3897 + YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN 3898 + ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE 3899 + BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is 3900 + I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G 3901 + CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do 3902 + lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc 3903 + AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k 3904 + -----END CERTIFICATE----- 3905 + 3906 + -----BEGIN CERTIFICATE----- 3907 + MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ 3908 + BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh 3909 + c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy 3910 + MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp 3911 + emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X 3912 + DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw 3913 + FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg 3914 + UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo 3915 + YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 3916 + MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB 3917 + AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 3918 + pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 3919 + 13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID 3920 + AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk 3921 + U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i 3922 + F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY 3923 + oJ2daZH9 3924 + -----END CERTIFICATE----- 3925 + 3926 + -----BEGIN CERTIFICATE----- 3927 + MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw 3928 + CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl 3929 + cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu 3930 + LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT 3931 + aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp 3932 + dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD 3933 + VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT 3934 + aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ 3935 + bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu 3936 + IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 3937 + LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b 3938 + N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t 3939 + KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu 3940 + kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm 3941 + CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ 3942 + Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu 3943 + imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te 3944 + 2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe 3945 + DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC 3946 + /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p 3947 + F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt 3948 + TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== 3949 + -----END CERTIFICATE----- 3950 + 3951 + -----BEGIN CERTIFICATE----- 3952 + MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL 3953 + MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW 3954 + ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln 3955 + biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp 3956 + U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y 3957 + aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG 3958 + A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp 3959 + U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg 3960 + SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln 3961 + biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 3962 + IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm 3963 + GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve 3964 + fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw 3965 + AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ 3966 + aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj 3967 + aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW 3968 + kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC 3969 + 4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga 3970 + FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== 3971 + -----END CERTIFICATE----- 3972 + 3973 + -----BEGIN CERTIFICATE----- 3974 + MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB 3975 + yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL 3976 + ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp 3977 + U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW 3978 + ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 3979 + aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL 3980 + MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW 3981 + ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln 3982 + biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp 3983 + U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y 3984 + aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 3985 + nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex 3986 + t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz 3987 + SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG 3988 + BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ 3989 + rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ 3990 + NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E 3991 + BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH 3992 + BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy 3993 + aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv 3994 + MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE 3995 + p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y 3996 + 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK 3997 + WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ 3998 + 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N 3999 + hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq 4000 + -----END CERTIFICATE----- 4001 + 4002 + -----BEGIN CERTIFICATE----- 4003 + MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw 4004 + CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl 4005 + cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu 4006 + LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT 4007 + aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp 4008 + dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD 4009 + VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT 4010 + aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ 4011 + bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu 4012 + IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 4013 + LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 4014 + GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ 4015 + +mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd 4016 + U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm 4017 + NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY 4018 + ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ 4019 + ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 4020 + CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq 4021 + g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm 4022 + fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c 4023 + 2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ 4024 + bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== 4025 + -----END CERTIFICATE----- 4026 + 4027 + -----BEGIN CERTIFICATE----- 4028 + MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB 4029 + vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL 4030 + ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp 4031 + U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W 4032 + ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe 4033 + Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX 4034 + MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 4035 + IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y 4036 + IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh 4037 + bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF 4038 + AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF 4039 + 9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH 4040 + H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H 4041 + LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN 4042 + /BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT 4043 + rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud 4044 + EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw 4045 + WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs 4046 + exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud 4047 + DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 4048 + sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ 4049 + seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz 4050 + 4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ 4051 + BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR 4052 + lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 4053 + 7M2CYfE45k+XmCpajQ== 4054 + -----END CERTIFICATE----- 4055 + 4056 + -----BEGIN CERTIFICATE----- 4057 + MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr 4058 + MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl 4059 + cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv 4060 + bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw 4061 + CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h 4062 + dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l 4063 + cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h 4064 + 2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E 4065 + lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV 4066 + ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq 4067 + 299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t 4068 + vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL 4069 + dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD 4070 + AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF 4071 + AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR 4072 + zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 4073 + LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd 4074 + 7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw 4075 + ++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt 4076 + 398znM/jra6O1I7mT1GvFpLgXPYHDw== 4077 + -----END CERTIFICATE----- 4078 + 4079 + -----BEGIN CERTIFICATE----- 4080 + MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC 4081 + VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD 4082 + ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v 4083 + dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0 4084 + MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww 4085 + KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G 4086 + A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi 4087 + MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13 4088 + 5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE 4089 + SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O 4090 + JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu 4091 + ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE 4092 + AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB 4093 + AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB 4094 + CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw 4095 + b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo 4096 + 7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/ 4097 + 0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7 4098 + nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx 4099 + x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ 4100 + 33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= 4101 + -----END CERTIFICATE----- 4102 + 4103 + -----BEGIN CERTIFICATE----- 4104 + MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx 4105 + IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs 4106 + cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v 4107 + dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0 4108 + MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl 4109 + bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD 4110 + DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw 4111 + ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r 4112 + WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU 4113 + Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs 4114 + HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj 4115 + z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf 4116 + SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl 4117 + AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG 4118 + KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P 4119 + AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j 4120 + BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC 4121 + VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX 4122 + ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg 4123 + Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB 4124 + ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd 4125 + /ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB 4126 + A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn 4127 + k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9 4128 + iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv 4129 + 2G0xffX8oRAHh84vWdw+WNs= 4130 + -----END CERTIFICATE----- 4131 + 4132 + -----BEGIN CERTIFICATE----- 4133 + MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB 4134 + gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk 4135 + MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY 4136 + UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx 4137 + NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 4138 + dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy 4139 + dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB 4140 + dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 4141 + 38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP 4142 + KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q 4143 + DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 4144 + qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa 4145 + JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi 4146 + PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P 4147 + BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs 4148 + jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 4149 + eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD 4150 + ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR 4151 + vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt 4152 + qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa 4153 + IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy 4154 + i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ 4155 + O+7ETPTsJ3xCwnR8gooJybQDJbw= 4156 + -----END CERTIFICATE----- 4157 +
+14
vendor/opam/tls/certificates/foo.pem
··· 1 + -----BEGIN CERTIFICATE----- 2 + MIICHTCCAYYCCQDPsW8ipzRmaTANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJB 3 + VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 4 + cyBQdHkgTHRkMQwwCgYDVQQDDANmb28wHhcNMTQwODExMTIwOTI4WhcNMTUwODEx 5 + MTIwOTI4WjBTMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8G 6 + A1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQwwCgYDVQQDDANmb28wgZ8w 7 + DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZASN7mvCGUPaKrXrb42DcAf0F8D+M0 8 + ksOqL1U+TV4xQ0aJwm8r5o4A0oiw46v2/hGIRdlJiYUS8ZLL5J/VsIMfAcstJ02z 9 + pjj1vvs86Bq2tVk5NEQET+3WyhVPdr+9UlYIu1UKObvS7RLm1x+fhLohql4hgBUC 10 + ZxqrBJr4ZA2hAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAVE2BBZI/MTCZorKkGVVj 11 + ZFosVv4qhiajzT/yr3nd7/8vLMsHnqrkfwycES9s9RRE9glv1WNptFSxkUxKzP2r 12 + jv2c7jdkXkDZsLlCh/qmaaKymZ+WuATbGm/edItnwy3RQDzufjsTfOFUH/08JWwz 13 + rnWkhcnpCqdTTniWwy/HRYQ= 14 + -----END CERTIFICATE-----
+5
vendor/opam/tls/certificates/server-ec.key
··· 1 + -----BEGIN PRIVATE KEY----- 2 + MGACAQAwEAYHKoZIzj0CAQYFK4EEACMESTBHAgEBBEIAtmFgIVel9k9Ivp7S5Mlc 3 + adxdv3KvDHc1j787n4avTUpzk+Aj7g0zxen7UsBOk2q/EGbZbtVFsO4zdOvPqP1+ 4 + m94= 5 + -----END PRIVATE KEY-----
+14
vendor/opam/tls/certificates/server-ec.pem
··· 1 + -----BEGIN CERTIFICATE----- 2 + MIICDDCCAW+gAwIBAgIIQcOa7kqxp9cwCgYIKoZIzj0EAwQwFjEUMBIGA1UEAwwL 3 + ZXhhbXBsZS5jb20wHhcNMjEwNDA0MTcwMTU3WhcNMjIwNDA0MTcwMTU3WjAWMRQw 4 + EgYDVQQDDAtleGFtcGxlLmNvbTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAXIK 5 + VyKRhKOJjxXQtKJiTX9nM3lZs6qy632NYmG9BwJ74FidW1NYlT0eiN71nMHU9FOH 6 + BZ76AH0ISrbo3hjG7uFzAPMplhTwTlA7IcQoR8FOGjrN0w+H5YJZRtkfYU0hFETU 7 + F4quomVmbrxtcIgFRWLJdf7qciYYJyYc8ZlTZoHpZY02o2QwYjAdBgNVHQ4EFgQU 8 + nku+GxZTewB6/D2bJFQcOkBN4QMwDwYDVR0PAQH/BAUDAwfGADAPBgNVHRMBAf8E 9 + BTADAQH/MB8GA1UdIwQYMBaAFJ5LvhsWU3sAevw9myRUHDpATeEDMAoGCCqGSM49 10 + BAMEA4GKADCBhgJBfZBX4o5Df/fJUnzmQKo6KFFWlc70VkO3hXH6lUhVRLcT+Ame 11 + 6gJUjgYy65GryW4Tx/pFTI7tdX19UDm+kBvgv1sCQRIgxgt/eJ74VsRgt7Br3Smm 12 + px1uULyS4PIGBKT4O4C4bWS1wdzw8ZOlegss1+pkxYYrfJFNJYyBaqY0ScTpvE4F 13 + -----END CERTIFICATE----- 14 + ----
+15
vendor/opam/tls/certificates/server.key
··· 1 + -----BEGIN RSA PRIVATE KEY----- 2 + MIICXQIBAAKBgQC2QEje5rwhlD2iq162+Ng3AH9BfA/jNJLDqi9VPk1eMUNGicJv 3 + K+aOANKIsOOr9v4RiEXZSYmFEvGSy+Sf1bCDHwHLLSdNs6Y49b77POgatrVZOTRE 4 + BE/t1soVT3a/vVJWCLtVCjm70u0S5tcfn4S6IapeIYAVAmcaqwSa+GQNoQIDAQAB 5 + AoGAd/CShG8g/JBMh9Nz/8KAuKHRHc2BvysIM1C62cSosgaFmdRrazJfBrEv3Nlc 6 + 2/0uc2dVYIxuvm8bIFqi2TWOdX9jWJf6oXwEPXCD0SaDbJTaoh0b+wjyHuaGlttY 7 + Ztvmf8mK1BOhyl3vNMxh/8Re0dGvGgPZHpn8zanaqfGVz+ECQQDngieUpwzxA0QZ 8 + GZKRYhHoLEaPiQzBaXphqWcCLLN7oAKxZlUCUckxRRe0tKINf0cB3Kr9gGQjPpm0 9 + YoqXo8mNAkEAyYgdd+JDi9FH3Cz6ijvPU0hYkriwTii0V09+Ar5DvYQNzNEIEJu8 10 + Q3Yte/TPRuK8zhnp97Bsy9v/Ji/LSWbtZQJBAJe9y8u3otfmWCBLjrIUIcCYJLe4 11 + ENBFHp4ctxPJ0Ora+mjkthuLF+BfdSZQr1dBcX1a8giuuvQO+Bgv7r9t75ECQC7F 12 + omEyaA7JEW5uGe9/Fgz0G2ph5rkdBU3GKy6jzcDsJu/EC6UfH8Bgawn7tSd0c/E5 13 + Xm2Xyog9lKfeK8XrV2kCQQCTico5lQPjfIwjhvn45ALc/0OrkaK0hQNpXgUNFJFQ 14 + tuX2WMD5flMyA5PCx5XBU8gEMHYa8Kr5d6uoixnbS0cZ 15 + -----END RSA PRIVATE KEY-----
+15
vendor/opam/tls/certificates/server.pem
··· 1 + -----BEGIN CERTIFICATE----- 2 + MIICYzCCAcwCCQDLbE6ES1ih1DANBgkqhkiG9w0BAQUFADB2MQswCQYDVQQGEwJB 3 + VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 4 + cyBQdHkgTHRkMRUwEwYDVQQDDAxZT1VSIE5BTUUhISExGDAWBgkqhkiG9w0BCQEW 5 + CW1lQGJhci5kZTAeFw0xNDAyMTcyMjA4NDVaFw0xNTAyMTcyMjA4NDVaMHYxCzAJ 6 + BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l 7 + dCBXaWRnaXRzIFB0eSBMdGQxFTATBgNVBAMMDFlPVVIgTkFNRSEhITEYMBYGCSqG 8 + SIb3DQEJARYJbWVAYmFyLmRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2 9 + QEje5rwhlD2iq162+Ng3AH9BfA/jNJLDqi9VPk1eMUNGicJvK+aOANKIsOOr9v4R 10 + iEXZSYmFEvGSy+Sf1bCDHwHLLSdNs6Y49b77POgatrVZOTREBE/t1soVT3a/vVJW 11 + CLtVCjm70u0S5tcfn4S6IapeIYAVAmcaqwSa+GQNoQIDAQABMA0GCSqGSIb3DQEB 12 + BQUAA4GBAIo4ZppIlp3JRyltRC1/AyCC0tsh5TdM3W7258wdoP3lEe08UlLwpnPc 13 + aJ/cX8rMG4Xf4it77yrbVrU3MumBEGN5TW4jn4+iZyFbp6TT3OUF55nsXDjNHBbu 14 + deDVpGuPTI6CZQVhU5qEMF3xmlokG+VV+HCDTglNQc+fdLM0LoNF 15 + -----END CERTIFICATE-----
+249
vendor/opam/tls/design.md
··· 1 + ### The OCaml-TLS architecture 2 + 3 + The OCaml ecosystem has several distinct ways of interacting with the outside world 4 + (and the network in particular): straightforward [unix][ocaml-unix] interfaces 5 + and the asynchronous programming libraries [lwt][] and [async][]. One of the 6 + early considerations was not to restrict ourselves to any of those -- we wanted 7 + to support them all. 8 + 9 + There were also two distinct basic "platforms" we wanted to target from the 10 + outset: the case of a simple executable, and the case of `Mirage` unikernels. 11 + 12 + So one of the first questions we faced was deciding how to represent 13 + interactions with the network in a portable way. This can be done by 14 + systematically abstracting out the API boundary which gives access to network 15 + operations, but we had a third thing in mind as well: we wanted to exploit the 16 + functional nature of OCaml to its fullest extent! 17 + 18 + Our various prior experiences with Haskell and Idris convinced us to adopt 19 + what is called "purely functional" technique. We believe it to be an approach 20 + which first forces the programmer to give principled answers to all the 21 + difficult design questions (errors and global data-flow) *in advance*, and then 22 + leads to far cleaner and composable code later on. A purely functional system 23 + has all the data paths made completely explicit in the form of function 24 + arguments and results. There are no unaccounted-for interactions between 25 + components mediated by shared state, and all the activity of the parts of the 26 + system is exposed through types since, after all, it's only about computing 27 + values from values. 28 + 29 + For these reasons, the library is split into two parts: the directory `/lib` 30 + (and the corresponding findlib package `tls`) contains the core TLS logic, and 31 + `/mirage` and `/lwt` (packaged as `tls.mirage` and `tls.lwt` respectively) 32 + contain front-ends that tie the core to `Mirage` and `Lwt_unix`. 33 + 34 + [ocaml-unix]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Unix.html 35 + [lwt]: http://ocsigen.org/lwt/ 36 + [async]: https://realworldocaml.org/v1/en/html/concurrent-programming-with-async.html 37 + 38 + ### Core 39 + 40 + The [core][tls-engine-mli] library is purely functional. A TLS session is represented by the 41 + abstract type `Tls.Engine.state`, and various functions consume this session 42 + type together with raw bytes (`Cstruct.t` -- which is by itself mutable, but 43 + `ocaml-tls` eschews this) and produce new session values and resulting buffers. 44 + 45 + The central entry point is [handle_tls][], which transforms an input state and a 46 + buffer to an output state, a (possibly empty) buffer to send to the 47 + communication partner, and an optional buffer of data intended to be received by 48 + the application: 49 + 50 + ```OCaml 51 + type state 52 + 53 + type ret = [ 54 + | `Ok of [ `Ok of state | `Eof | `Alert of alert ] * 55 + [ `Response of Cstruct.t ] * [ `Data of Cstruct.t option ] 56 + | `Fail of alert * [ `Response of Cstruct.t ] 57 + ] 58 + 59 + val handle_tls : state -> Cstruct.t -> ret 60 + ``` 61 + 62 + As the signature shows, errors are signalled through the `ret` type, which is a [polymorphic variant][poly]. This 63 + reflects the actual internal structure: all the errors are represented as 64 + values, and operations are composed using an error [monad][monad-ml]. 65 + 66 + Other entry points share the same basic behaviour: they transform the prior 67 + state and input bytes into the later state and output bytes. 68 + 69 + Here's a rough outline of what happens in `handle_tls`: 70 + 71 + - TLS packets consist of a header, which contains the protocol 72 + version, length, and content type, and the payload of the given 73 + content type. Once inside our [main handler][handle_tls], we 74 + [separate][separate_records] the buffer into TLS records, and 75 + [process][handle_raw_record] each individually. We first check that 76 + the version number is correct, then [decrypt][decrypt], and [verify 77 + the mac][verify_mac]. 78 + 79 + - Decrypted data is then [dispatched][handle_packet] to one of four 80 + sub-protocol handlers (Handshake, Change Cipher Spec, Alert and 81 + Application Data). Each handler can [return][return_types] a new 82 + handshake state, outgoing data, application data, the new decryption 83 + state or an error (with the outgoing data being an interleaved list 84 + of buffers and new encryption states). 85 + 86 + - The outgoing buffers and the encryption states are 87 + [traversed][encrypt] to produce the final output to be sent to the 88 + communication partner, and the final encryption, decryption and 89 + handshake states are combined into a new overall state which is 90 + returned to the caller. 91 + 92 + Handshake is (by far) the most complex TLS sub-protocol, with an elaborate state 93 + machine. Our [client][client_handshake] and [server][server_handshake] encode 94 + this state as a "flat" [sum type][handshake_states], with exactly one incoming 95 + message allowed per state. The handlers first [parse][parse_handshake] the 96 + handshake packet (which fails in case of malformed or unknown data) and then 97 + dispatch it to the handling function. The [handshake state][handshake_state] is 98 + carried around and a fresh one is returned from the handler in case it needs 99 + updates. It consists of a protocol version, the handshake state, configuration, 100 + renegotiation data, and possibly a handshake fragment. 101 + 102 + Logic of both handshake handlers is very localised, and does not mutate any 103 + global data structures. 104 + 105 + [poly]: https://realworldocaml.org/v1/en/html/variants.html#polymorphic-variants 106 + [monad-ml]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/control.ml 107 + [return_types]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/state.ml#L109 108 + [encrypt]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L48 109 + [handle_packet]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L240 110 + [verify_mac]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L85 111 + [decrypt]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L95 112 + [handle_tls]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L321 113 + [handle_raw_record]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L275 114 + [separate_records]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L150 115 + 116 + [handshake_state]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/state.ml#L92 117 + [parse_handshake]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/reader.ml#L361 118 + [separate_handshakes]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.ml#L217 119 + [handshake_states]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/state.ml#L61 120 + [server_handshake]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/handshake_server.ml#L247 121 + [client_handshake]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/handshake_client.ml#L285 122 + 123 + ### Core API 124 + 125 + OCaml permits the implementation a module to be exported via a more 126 + abstract *signature* that hides the internal representation 127 + details. Our public API for the core library consists of the 128 + [Tls.Engine][tls-engine-mli] and [Tls.Config][tls-config-mli] modules. 129 + 130 + `Tls.Engine` contains the basic reactive function `handle_tls`, mentioned above, 131 + which processes incoming data and optionally produces a response, together with 132 + several operations that allow one to initiate message transfer like 133 + `send_application_data` (which processes application-level messages for 134 + sending), `send_close_notify` (for sending the ending message) and `reneg` 135 + (which initiates full TLS renegotiation). 136 + 137 + The module also contains the only two ways to obtain the initial state: 138 + 139 + ```OCaml 140 + val client : Config.client -> (state * Cstruct.t) 141 + val server : Config.server -> state 142 + ``` 143 + 144 + That is, one needs a configuration value to create it. The `Cstruct.t` 145 + that `client` emits is the initial Client Hello since in TLS, 146 + the client starts the session. 147 + 148 + `Tls.Config` synthesizes configurations, separately for client and server 149 + endpoints, through the functions `client_exn` and `server_exn`. They take a 150 + number of parameters that define a TLS session, check them for consistency, and 151 + return the sanitized `config` value which can be used to create a `state` and, 152 + thus, a session. If the check fails, they raise an exception. 153 + 154 + The parameters include the pair of a certificate and its private key for the 155 + server, and an `X509.Authenticator.t` for the client, both produced by our 156 + [ocaml-x509][] library and described in a [previous article][x509-intro]. 157 + 158 + This design reflects our attempts to make the API as close to "fire and forget" 159 + as we could, given the complexity of TLS: we wanted the library to be relatively 160 + straightforward to use, have a minimal API footprint and, above all, fail very 161 + early and very loudly when misconfigured. 162 + 163 + [tls-engine-mli]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/engine.mli 164 + 165 + [tls-config-mli]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lib/config.mli 166 + 167 + [ocaml-x509]: https://github.com/mirleft/ocaml-x509 168 + 169 + 170 + ### Effectful front-ends 171 + 172 + Clearly, reading and writing network data *does* change the state of the world. 173 + Having a pure value describing the state of a TLS session is not really useful 174 + once we write something onto the network; it is certainly not the case that we 175 + can use more than one distinct `state` to process further data, as only one 176 + value is in sync with the other endpoint at any given time. 177 + 178 + Therefore we wrap the core types into stateful structures loosely inspired by 179 + sockets and provide IO operations on those. The structures of `mirage` and `lwt` 180 + front-ends mirror one another. 181 + 182 + In both cases, the structure is pull-based in the sense that no processing is 183 + done until the client requires a read, as opposed to a callback-driven design 184 + where the client registers a callback and the library starts spinning in a 185 + listening loop and invoking it as soon as there is data to be processed. We do 186 + this because in an asynchronous context, it is easy to create a callback-driven 187 + interface from a demand-driven one, but the opposite is possible only with 188 + unbounded buffering of incoming data. 189 + 190 + One exception to demand-driven design is the initial session creation: the 191 + library will only yield the connection after the first handshake is over, 192 + ensuring the invariant that it is impossible to interact with a connection if it 193 + hasn't already been fully established. 194 + 195 + **Mirage** 196 + 197 + The `Mirage` [interface][tls_mirage_types_mli] matches the [FLOW][flow] 198 + signature (with additional TLS-specific operations). We provide a functor that 199 + needs to be applied to an underlying TCP module, to obtain a TLS transport on 200 + top. For example: 201 + 202 + ```OCaml 203 + module Server (Stack: STACKV4) (KV: KV_RO) = 204 + struct 205 + 206 + module TLS = Tls_mirage.Make (Stack.TCPV4) 207 + module X509 = Tls_mirage.X509 (KV) (Clock) 208 + 209 + let accept conf flow = 210 + TLS.server_of_tcp_flow conf flow >>= function 211 + | `Ok tls -> 212 + TLS.read tls >>= function 213 + | `Ok buf -> 214 + TLS.write tls buf >>= fun () -> TLS.close buf 215 + 216 + let start stack e kv = 217 + lwt authenticator = X509.authenticator kv `Default in 218 + let conf = Tls.Config.server_exn ~authenticator () in 219 + Stack.listen_tcpv4 stack 4433 (accept conf) ; 220 + Stack.listen stack 221 + 222 + end 223 + ``` 224 + 225 + **Lwt** 226 + 227 + The `lwt` interface has [two layers][tls_lwt_mli]. `Tls_lwt.Unix` is loosely based 228 + on read/write operations from `Lwt_unix` and provides in-place update of 229 + buffers. `read`, for example, takes a `Cstruct.t` to write into and returns the 230 + number of bytes read. The surrounding module, `Tls_lwt`, provides a simpler, 231 + `Lwt_io`-compatible API built on top: 232 + 233 + ```OCaml 234 + let main host port = 235 + lwt authenticator = X509_lwt.authenticator (`Ca_dir nss_trusted_ca_dir) in 236 + lwt (ic, oc) = Tls_lwt.connect ~authenticator (host, port) in 237 + let req = String.concat "\r\n" [ 238 + "GET / HTTP/1.1" ; "Host: " ^ host ; "Connection: close" ; "" ; "" 239 + ] in 240 + Lwt_io.(write oc req >>= fun () -> read ic >>= print) 241 + ``` 242 + 243 + We have further plans to provide wrappers for [`Async`][async] and plain [`Unix`][ocaml-unix] in a 244 + similar vein. 245 + 246 + [tls_mirage_types_mli]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/mirage/tls_mirage_types.mli 247 + [flow]: https://github.com/mirage/mirage/blob/ae3c966f8d726dc97208595b8005e02e39478cb1/types/V1.mli#L136 248 + [example_unikernel]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/mirage/example/unikernel.ml 249 + [tls_lwt_mli]: https://github.com/mirleft/ocaml-tls/blob/6dc9258a38489665abf2bd6cdbed8a1ba544d522/lwt/tls_lwt.mli
+4
vendor/opam/tls/dune-project
··· 1 + (lang dune 3.0) 2 + (name tls) 3 + (formatting disabled) 4 + (using mdx 0.2)
+5
vendor/opam/tls/eio/dune
··· 1 + (library 2 + (name tls_eio) 3 + (public_name tls-eio) 4 + (wrapped false) 5 + (libraries tls eio ptime.clock.os))
+30
vendor/opam/tls/eio/tests/dune
··· 1 + (copy_files ../../certificates/*.crt) 2 + (copy_files ../../certificates/*.key) 3 + (copy_files ../../certificates/*.pem) 4 + 5 + (mdx 6 + (package tls-eio) 7 + (deps 8 + server.pem 9 + server.key 10 + server-ec.pem 11 + server-ec.key 12 + (package tls-eio) 13 + (package mirage-crypto-rng) 14 + (package eio_main))) 15 + 16 + ; "dune runtest" just does a quick run with random inputs. 17 + ; 18 + ; To run with afl-fuzz instead (make sure you have a compiler with the afl option on!): 19 + ; 20 + ; dune runtest 21 + ; mkdir input 22 + ; echo hi > input/foo 23 + ; cp certificates/server.{key,pem} . 24 + ; afl-fuzz -m 1000 -i input -o output ./_build/default/eio/tests/fuzz.exe @@ 25 + (test 26 + (package tls-eio) 27 + (libraries crowbar tls-eio eio.mock logs logs.fmt) 28 + (deps server.pem server.key) 29 + (name fuzz) 30 + (action (run %{test} --repeat 200)))
+297
vendor/opam/tls/eio/tests/fuzz.ml
··· 1 + (* Fuzz testing for tls-eio. 2 + 3 + This code picks two random strings, one for the client to send and one for 4 + the server. It then starts a send and receive fiber for each end. 5 + 6 + A dispatcher fiber then sends commands to these worker fibers 7 + (see [action] for the possible actions). 8 + 9 + This is intended to check for bugs in the Eio wrapper (rather than in Tls itself). 10 + At the moment, it's just checking that tls-eio works when used correctly. 11 + Each endpoint overlaps reads with writes (but not reads with other reads or 12 + writes with other writes). 13 + 14 + Some possible future improvements: 15 + 16 + - It currently only checks the basic read/write/close operations. 17 + It should be extended to check [reneg], etc too. 18 + 19 + - Currently, cancelling a read operation marks the Tls flow as broken. 20 + We should allow resuming after a cancelled read, and test that here. 21 + 22 + - We should try injecting faults and make sure they're handled sensibly. 23 + 24 + - It would be good to get coverage reports for these tests. 25 + However, this requires changes to crowbar: 26 + https://github.com/stedolan/crowbar/issues/4#issuecomment-1310277551 27 + (a patched version reported 54% coverage of Tls_eio.ml) *) 28 + 29 + open Eio.Std 30 + 31 + let src = Logs.Src.create "fuzz" ~doc:"Fuzz tests" 32 + module Log = (val Logs.src_log src : Logs.LOG) 33 + 34 + module W = Eio.Buf_write 35 + 36 + type transmit_amount = Mock_socket.transmit_amount 37 + 38 + type op = 39 + | Send of int (* The application sends some bytes to Tls *) 40 + | Transmit of transmit_amount (* The network sends some types to the peer *) 41 + | Recv (* The application tries to read some data *) 42 + | Shutdown_send (* The application shuts down the sending side *) 43 + 44 + let label name gen = 45 + Crowbar.with_printer Fmt.(const string name) gen 46 + 47 + let op = 48 + Crowbar.choose @@ [ 49 + Crowbar.(map [range 4096]) (fun n -> Send n); 50 + Crowbar.(map [range ~min:1 4096]) (fun n -> Transmit (`Bytes n)); 51 + label "recv" @@ Crowbar.const Recv; 52 + label "shutdown-send" @@ Crowbar.const Shutdown_send; 53 + ] 54 + 55 + type dir = To_client | To_server 56 + 57 + let pp_dir f = function 58 + | To_server -> Fmt.string f "client-to-server" 59 + | To_client -> Fmt.string f "server-to-client" 60 + 61 + let dir = 62 + Crowbar.choose [ 63 + label "server-to-client" @@ Crowbar.const To_client; 64 + label "client-to-server" @@ Crowbar.const To_server; 65 + ] 66 + 67 + (* A test case is a random sequence of [action]s, followed by party shutting 68 + down the sending side of the connection (if it hasn't already done so) and 69 + the network draining any queued traffic. 70 + 71 + Once all fibers have finished, we check that what was sent matches the data 72 + that has been received. *) 73 + 74 + let action = 75 + Crowbar.option (Crowbar.pair dir op) (* None means yield *) 76 + 77 + (* A [Path] is one direction (either server-to-client or client-to-server). 78 + The two paths can be tested mostly independently (except for shutdown at the moment). *) 79 + module Path : sig 80 + type t 81 + 82 + val create : 83 + sender:(Tls_eio.t, exn) result Promise.t -> 84 + receiver:(Tls_eio.t, exn) result Promise.t -> 85 + transmit:(transmit_amount -> unit) -> 86 + dir -> string -> t 87 + (** Create a test driver for one direction, from [sender] to [receiver]. 88 + [transmit n] causes [n] bytes to be transferred over the mock network. *) 89 + 90 + val close : t -> unit 91 + (** [close t] causes the sender to close the socket for sending. 92 + Futher send operations will be ignored. *) 93 + 94 + val run : t -> unit 95 + (** Run the send and receive fibers. Returns once the receiver has read EOF. *) 96 + 97 + val enqueue : t -> op -> unit 98 + (** Send a command to the send or receive fiber (depending on [op]). *) 99 + end = struct 100 + type t = { 101 + dir : dir; 102 + message : string; (* The complete message to be transmitted over this path. *) 103 + (* We need to construct [t] before the handshake is done, so these are promises: *) 104 + sender : Tls_eio.t Promise.or_exn; 105 + receiver : Tls_eio.t Promise.or_exn; 106 + mutable sent : int; (* Bytes of [message] sent so far *) 107 + mutable recv : int; (* Bytes of [message] received so far *) 108 + send_commands : [`Send of int | `Exit] Eio.Stream.t; (* Commands for the sending fiber *) 109 + recv_commands : [`Recv | `Drain] Eio.Stream.t; (* Commands for the receiving fiber *) 110 + transmit : transmit_amount -> unit; 111 + } 112 + 113 + let pp_dir f t = 114 + pp_dir f t.dir 115 + 116 + let create ~sender ~receiver ~transmit dir message = 117 + let send_commands = Eio.Stream.create max_int in 118 + let recv_commands = Eio.Stream.create max_int in 119 + { dir; message; sender; receiver; sent = 0; recv = 0; 120 + send_commands; recv_commands; transmit } 121 + 122 + let shutdown t = 123 + Eio.Stream.add t.send_commands `Exit 124 + 125 + let close t = 126 + shutdown t; (* Sender stops sending *) 127 + t.transmit `Drain; (* Network transmits everything *) 128 + Eio.Stream.add t.recv_commands `Drain (* Receiver reads everything *) 129 + 130 + let run_send_thread t = 131 + let sender = Promise.await_exn t.sender in 132 + Logs.info (fun f -> f "%a: sender ready" pp_dir t); 133 + let rec aux () = 134 + match Eio.Stream.take t.send_commands with 135 + | `Exit -> 136 + Log.info (fun f -> f "%a: shutdown send (Tls level)" pp_dir t); 137 + Eio.Flow.shutdown sender `Send 138 + | `Send len -> 139 + let available = String.length t.message - t.sent in 140 + let len = min len available in 141 + if len > 0 then ( 142 + let msg = Cstruct.of_string ~off:t.sent ~len t.message in 143 + t.sent <- t.sent + len; 144 + Log.info (fun f -> f "%a: sending %S" pp_dir t (Cstruct.to_string msg)); 145 + Eio.Flow.write sender [msg]; 146 + ); 147 + aux () 148 + in 149 + aux() 150 + 151 + let run_recv_thread t = 152 + let recv = Promise.await_exn t.receiver in 153 + Logs.info (fun f -> f "%a: receiver ready" pp_dir t); 154 + try 155 + let drain = ref false in 156 + while true do 157 + if !drain = false then ( 158 + begin match Eio.Stream.take t.recv_commands with 159 + | `Recv -> () 160 + | `Drain -> drain := true 161 + end 162 + ); 163 + let buf = Cstruct.create 4096 in 164 + let got = Eio.Flow.single_read recv buf in 165 + let received = Cstruct.to_string buf ~len:got in 166 + Log.info (fun f -> f "%a: received %S" pp_dir t received); 167 + let expected = String.sub t.message t.recv got in 168 + if received <> expected then 169 + Fmt.failwith "%a: excepted %S but got %S!" pp_dir t expected received; 170 + t.recv <- t.recv + got 171 + done 172 + with End_of_file -> 173 + if t.recv <> t.sent then ( 174 + Fmt.failwith "%a: Sender sent %d bytes, but receiver got EOF after reading only %d" 175 + pp_dir t 176 + t.sent 177 + t.recv 178 + ); 179 + Log.info (fun f -> f "%a: recv thread done (got EOF)" pp_dir t) 180 + 181 + let run t = 182 + Fiber.both 183 + (fun () -> run_send_thread t) 184 + (fun () -> run_recv_thread t) 185 + 186 + let pp_amount f = function 187 + | `Bytes n -> Fmt.pf f "%d bytes" n 188 + | `Drain -> Fmt.string f "all bytes" 189 + 190 + let enqueue t = function 191 + | Send i-> 192 + Log.info (fun f -> f "%a: enqueue send %d bytes of plaintext" pp_dir t i); 193 + Eio.Stream.add t.send_commands @@ `Send i; 194 + | Recv -> 195 + Log.info (fun f -> f "%a: enqueue read from Tls" pp_dir t); 196 + Eio.Stream.add t.recv_commands @@ `Recv; 197 + | Transmit i -> 198 + Log.info (fun f -> f "%a: enqueue transmit %a over network" pp_dir t pp_amount i); 199 + t.transmit i 200 + | Shutdown_send -> 201 + Log.info (fun f -> f "%a: enqueue shutdown send" pp_dir t); 202 + shutdown t 203 + end 204 + 205 + module Config : sig 206 + val client : Tls.Config.client 207 + val server : Tls.Config.server 208 + end = struct 209 + let null_auth ?ip:_ ~host:_ _ = Ok None 210 + 211 + let client = 212 + Result.get_ok (Tls.Config.client ~authenticator:null_auth ()) 213 + 214 + let read_file path = 215 + let ch = open_in_bin path in 216 + let len = in_channel_length ch in 217 + let data = really_input_string ch len in 218 + close_in ch; 219 + data 220 + 221 + let server = 222 + let certs = Result.get_ok (X509.Certificate.decode_pem_multiple (read_file "server.pem")) in 223 + let pk = Result.get_ok (X509.Private_key.decode_pem (read_file "server.key")) in 224 + let certificates = `Single (certs, pk) in 225 + Result.get_ok Tls.Config.(server ~version:(`TLS_1_0, `TLS_1_3) ~certificates ~ciphers:Ciphers.supported ()) 226 + end 227 + 228 + let dispatch_commands ~to_server ~to_client actions = 229 + let rec aux = function 230 + | [] -> 231 + Log.info (fun f -> f "dispatch_commands: done"); 232 + Path.close to_client; 233 + Path.close to_server 234 + | None :: xs -> 235 + Fiber.yield (); aux xs 236 + | Some (dir, op) :: xs -> 237 + let path = 238 + match dir with 239 + | To_server-> to_server 240 + | To_client -> to_client 241 + in 242 + Path.enqueue path op; 243 + aux xs 244 + in 245 + aux actions 246 + 247 + (* In some runs we automatically perform these actions first, which allows the handshake to complete. 248 + This lets the fuzz tester get to the interesting cases more quickly. *) 249 + let quickstart_actions = [ 250 + Some (To_server, Transmit (`Bytes 4096)); 251 + None; (* Client sends handshake *) 252 + None; (* Server reads handshake *) 253 + Some (To_client, Transmit (`Bytes 4096)); 254 + None; (* Server replies to handshake *) 255 + None; (* Client reads reply *) 256 + Some (To_server, Transmit (`Bytes 4096)); 257 + None; (* Client sends final part *) 258 + None; (* Server receives it *) 259 + Some (To_client, Recv); 260 + Some (To_server, Recv); 261 + ] 262 + 263 + let main client_message server_message quickstart actions = 264 + let actions = 265 + if quickstart then quickstart_actions @ actions 266 + else actions 267 + in 268 + Eio_mock.Backend.run @@ fun () -> 269 + Switch.run @@ fun sw -> 270 + let insecure_test_rng = Mirage_crypto_rng.create (module Test_rng) in 271 + Mirage_crypto_rng.set_default_generator insecure_test_rng; 272 + let client_socket, server_socket = Mock_socket.create_pair () in 273 + let server_flow = Fiber.fork_promise ~sw (fun () -> Tls_eio.server_of_flow Config.server server_socket) in 274 + let client_flow = Fiber.fork_promise ~sw (fun () -> Tls_eio.client_of_flow Config.client client_socket) in 275 + let to_server = 276 + Path.create 277 + ~sender:client_flow 278 + ~receiver:server_flow 279 + ~transmit:(Mock_socket.transmit client_socket) 280 + To_server client_message in 281 + let to_client = 282 + Path.create 283 + ~sender:server_flow 284 + ~receiver:client_flow 285 + ~transmit:(Mock_socket.transmit server_socket) 286 + To_client server_message 287 + in 288 + Fiber.all [ 289 + (fun () -> dispatch_commands actions ~to_server ~to_client); 290 + (fun () -> Path.run to_server); 291 + (fun () -> Path.run to_client); 292 + ] 293 + 294 + let () = 295 + Logs.set_level (Some Warning); 296 + Logs.set_reporter (Logs_fmt.reporter ()); 297 + Crowbar.(add_test ~name:"random ops" [bytes; bytes; bool; list action] main)
+94
vendor/opam/tls/eio/tests/mock_socket.ml
··· 1 + open Eio.Std 2 + 3 + module W = Eio.Buf_write 4 + 5 + let src = Logs.Src.create "mock-socket" ~doc:"Test socket" 6 + module Log = (val Logs.src_log src : Logs.LOG) 7 + 8 + type transmit_amount = [`Bytes of int | `Drain] 9 + 10 + type ty = [`Mock_tls | Eio.Flow.two_way_ty | Eio.Resource.close_ty] 11 + type t = ty r 12 + 13 + let rec takev len = function 14 + | [] -> [] 15 + | x :: xs -> 16 + if len = 0 then [] 17 + else if Cstruct.length x >= len then [Cstruct.sub x 0 len] 18 + else x :: takev (len - Cstruct.length x) xs 19 + 20 + module Impl = struct 21 + type t = { 22 + to_peer : W.t; 23 + from_peer : W.t; 24 + label : string; 25 + output_sizes : transmit_amount Eio.Stream.t; 26 + } 27 + 28 + let create ~to_peer ~from_peer label = { 29 + to_peer; 30 + from_peer; 31 + label; 32 + output_sizes = Eio.Stream.create max_int; 33 + } 34 + 35 + let transmit t x = 36 + Eio.Stream.add t.output_sizes x 37 + 38 + let single_write t bufs = 39 + let size = 40 + match Eio.Stream.take t.output_sizes with 41 + | `Drain -> Eio.Stream.add t.output_sizes `Drain; Cstruct.lenv bufs 42 + | `Bytes size -> size 43 + in 44 + let bufs = takev size bufs in 45 + List.iter (W.cstruct t.to_peer) bufs; 46 + let len = Cstruct.lenv bufs in 47 + Log.info (fun f -> f "%s: wrote %d bytes to network" t.label len); 48 + len 49 + 50 + let copy t ~src = Eio.Flow.Pi.simple_copy ~single_write t ~src 51 + 52 + let single_read t buf = 53 + let batch = W.await_batch t.from_peer in 54 + let got, _ = Cstruct.fillv ~src:batch ~dst:buf in 55 + Log.info (fun f -> f "%s: read %d bytes from network" t.label got); 56 + W.shift t.from_peer got; 57 + got 58 + 59 + let shutdown t = function 60 + | `Send -> 61 + Log.info (fun f -> f "%s: close writer" t.label); 62 + W.close t.to_peer 63 + | _ -> failwith "Not implemented" 64 + 65 + let close t = 66 + Log.info (fun f -> f "%s: close connection" t.label) 67 + 68 + let read_methods = [] 69 + 70 + type (_, _, _) Eio.Resource.pi += Raw : ('t, 't -> t, ty) Eio.Resource.pi 71 + let raw (Eio.Resource.T (t, ops)) = Eio.Resource.get ops Raw t 72 + end 73 + 74 + let handler = 75 + Eio.Resource.handler ( 76 + H (Impl.Raw, Fun.id) :: 77 + H (Eio.Resource.Close, Impl.close) :: 78 + Eio.Resource.bindings (Eio.Flow.Pi.two_way (module Impl)) 79 + ) 80 + 81 + let transmit t x = 82 + let t = Impl.raw t in 83 + Impl.transmit t x 84 + 85 + let create ~from_peer ~to_peer label = 86 + let t = Impl.create ~from_peer ~to_peer label in 87 + Eio.Resource.T (t, handler) 88 + 89 + let create_pair () = 90 + let to_a = W.create 100 in 91 + let to_b = W.create 100 in 92 + let a = create ~from_peer:to_a ~to_peer:to_b "client" in 93 + let b = create ~from_peer:to_b ~to_peer:to_a "server" in 94 + a, b
+13
vendor/opam/tls/eio/tests/mock_socket.mli
··· 1 + open Eio.Std 2 + 3 + type transmit_amount = [ 4 + | `Bytes of int (* Send the next n bytes of data *) 5 + | `Drain (* Transmit all data immediately from now on *) 6 + ] 7 + 8 + type t = [`Mock_tls | Eio.Flow.two_way_ty | Eio.Resource.close_ty] r 9 + 10 + val create_pair : unit -> t * t 11 + (** Create a pair of sockets [client, server], such that writes to one can be read from the other. *) 12 + 13 + val transmit : t -> transmit_amount -> unit
+21
vendor/opam/tls/eio/tests/test_rng.ml
··· 1 + (* Insecure predictable RNG for fuzz testing. *) 2 + 3 + type g = int ref 4 + 5 + let block = 1 6 + 7 + let create ?time:_ () = ref 1234 8 + 9 + let generate_into ~g buf ~off n = 10 + for i = off to off + n - 1 do 11 + Bytes.set_uint8 buf i !g; 12 + g := !g + 1 13 + done 14 + 15 + let reseed ~g:_ _ = () 16 + 17 + let accumulate ~g:_ _ = `Acc ignore 18 + 19 + let seeded ~g:_ = true 20 + 21 + let pools = 0
+114
vendor/opam/tls/eio/tests/tls_eio.md
··· 1 + ```ocaml 2 + # #require "digestif.c";; 3 + # #require "eio_main";; 4 + # #require "tls-eio";; 5 + # #require "mirage-crypto-rng.unix";; 6 + ``` 7 + 8 + ```ocaml 9 + open Eio.Std 10 + 11 + module Flow = Eio.Flow 12 + ``` 13 + 14 + ## Test client 15 + 16 + ```ocaml 17 + let null_auth ?ip:_ ~host:_ _ = Ok None 18 + 19 + let mypsk = ref None 20 + 21 + let ticket_cache = { 22 + Tls.Config.lookup = (fun _ -> None) ; 23 + ticket_granted = (fun psk epoch -> mypsk := Some (psk, epoch)) ; 24 + lifetime = 0l ; 25 + timestamp = Ptime_clock.now 26 + } 27 + 28 + let test_client ~net (host, service) = 29 + match Eio.Net.getaddrinfo_stream net host ~service with 30 + | [] -> failwith "No addresses found!" 31 + | addr :: _ -> 32 + let authenticator = null_auth in 33 + Switch.run @@ fun sw -> 34 + let socket = Eio.Net.connect ~sw net addr in 35 + let flow = 36 + let host = 37 + Result.to_option 38 + (Result.bind (Domain_name.of_string host) Domain_name.host) 39 + in 40 + Tls_eio.client_of_flow 41 + (Result.get_ok Tls.Config.(client ~version:(`TLS_1_0, `TLS_1_3) ?cached_ticket:!mypsk ~ticket_cache ~authenticator ~ciphers:Ciphers.supported ())) 42 + ?host socket 43 + in 44 + let req = String.concat "\r\n" [ 45 + "GET / HTTP/1.1" ; "Host: " ^ host ; "Connection: close" ; "" ; "" 46 + ] in 47 + Flow.copy_string req flow; 48 + let r = Eio.Buf_read.of_flow flow ~max_size:max_int in 49 + let line = Eio.Buf_read.take 3 r in 50 + traceln "client <- %s" line; 51 + Eio.Resource.close flow; 52 + traceln "client done." 53 + ``` 54 + 55 + ## Test server 56 + 57 + ```ocaml 58 + let server_config dir = 59 + let ( / ) = Eio.Path.( / ) in 60 + let certificate = 61 + X509_eio.private_of_pems 62 + ~cert:(dir / "server.pem") 63 + ~priv_key:(dir / "server.key") 64 + in 65 + let ec_certificate = 66 + X509_eio.private_of_pems 67 + ~cert:(dir / "server-ec.pem") 68 + ~priv_key:(dir / "server-ec.key") 69 + in 70 + let certificates = `Multiple [ certificate ; ec_certificate ] in 71 + Result.get_ok Tls.Config.(server ~version:(`TLS_1_0, `TLS_1_3) ~certificates ~ciphers:Ciphers.supported ()) 72 + 73 + let serve_ssl ~config server_s callback = 74 + Switch.run @@ fun sw -> 75 + let client, addr = Eio.Net.accept ~sw server_s in 76 + let flow = Tls_eio.server_of_flow config client in 77 + traceln "server -> connect"; 78 + callback flow addr 79 + ``` 80 + 81 + ## Test case 82 + 83 + ```ocaml 84 + # Eio_main.run @@ fun env -> 85 + let net = env#net in 86 + let certificates_dir = env#cwd in 87 + Mirage_crypto_rng_unix.use_default (); 88 + Switch.run @@ fun sw -> 89 + let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, 4433) in 90 + let listening_socket = Eio.Net.listen ~sw net ~backlog:5 ~reuse_addr:true addr in 91 + (* Eio.Time.with_timeout_exn env#clock 0.1 @@ fun () -> *) 92 + Fiber.both 93 + (fun () -> 94 + traceln "server -> start @@ %a" Eio.Net.Sockaddr.pp addr; 95 + let config = server_config certificates_dir in 96 + serve_ssl ~config listening_socket @@ fun flow _addr -> 97 + traceln "handler accepted"; 98 + let r = Eio.Buf_read.of_flow flow ~max_size:max_int in 99 + let line = Eio.Buf_read.line r in 100 + traceln "handler + %s" line; 101 + Flow.copy_string line flow 102 + ) 103 + (fun () -> 104 + test_client ~net ("127.0.0.1", "4433") 105 + ) 106 + ;; 107 + +server -> start @ tcp:127.0.0.1:4433 108 + +server -> connect 109 + +handler accepted 110 + +handler + GET / HTTP/1.1 111 + +client <- GET 112 + +client done. 113 + - : unit = () 114 + ```
+250
vendor/opam/tls/eio/tls_eio.ml
··· 1 + open Eio.Std 2 + 3 + module Flow = Eio.Flow 4 + 5 + exception Tls_alert of Tls.Packet.alert_type 6 + exception Tls_failure of Tls.Engine.failure 7 + 8 + type Eio.Exn.Backend.t += Tls_socket_closed 9 + let () = Eio.Exn.Backend.register_pp (fun f -> function 10 + | Tls_socket_closed -> Fmt.pf f "TLS_socket_closed"; true 11 + | _ -> false 12 + ) 13 + 14 + type ty = [ `Tls | Eio.Flow.two_way_ty | Eio.Resource.close_ty ] 15 + type t = ty r 16 + 17 + module Raw = struct 18 + 19 + (* We could replace [`Eof] with [`Error End_of_file] and then use 20 + a regular [result] type here. *) 21 + type t = { 22 + flow : [Flow.two_way_ty | Eio.Resource.close_ty] r; 23 + mutable state : [ `Active of Tls.Engine.state 24 + | `Read_closed of Tls.Engine.state 25 + | `Write_closed of Tls.Engine.state 26 + | `Closed 27 + | `Error of exn ] ; 28 + mutable linger : Cstruct.t option ; 29 + recv_buf : Cstruct.t ; 30 + } 31 + 32 + let half_close state mode = 33 + match state, mode with 34 + | `Active tls, `read -> `Read_closed tls 35 + | `Active tls, `write -> `Write_closed tls 36 + | `Active _, `read_write -> `Closed 37 + | `Read_closed tls, `read -> `Read_closed tls 38 + | `Read_closed _, (`write | `read_write) -> `Closed 39 + | `Write_closed tls, `write -> `Write_closed tls 40 + | `Write_closed _, (`read | `read_write) -> `Closed 41 + | (`Closed | `Error _) as e, (`read | `write | `read_write) -> e 42 + 43 + let inject_state tls = function 44 + | `Active _ -> `Active tls 45 + | `Read_closed _ -> `Read_closed tls 46 + | `Write_closed _ -> `Write_closed tls 47 + | (`Closed | `Error _) as e -> e 48 + 49 + let write_t t s = 50 + try Flow.copy_string s t.flow 51 + with exn -> 52 + (match t.state with 53 + | `Error _ -> () 54 + | _ -> t.state <- `Error exn) ; 55 + raise exn 56 + 57 + let try_write_t t cs = 58 + try write_t t cs 59 + with _ -> Eio.Fiber.check () (* Error is in [t.state] *) 60 + 61 + let rec read_react t = 62 + 63 + let handle tls buf = 64 + match Tls.Engine.handle_tls tls buf with 65 + | Ok (state', eof, `Response resp, `Data data) -> 66 + let state' = inject_state state' t.state in 67 + let state' = Option.(value ~default:state' (map (fun `Eof -> half_close state' `read) eof)) in 68 + t.state <- state' ; 69 + Option.iter (try_write_t t) resp; 70 + Option.map Cstruct.of_string data 71 + 72 + | Error (fail, `Response resp) -> 73 + t.state <- `Error (match fail with `Alert a -> Tls_alert a | f -> Tls_failure f) ; 74 + write_t t resp; read_react t 75 + in 76 + 77 + match t.state with 78 + | `Error e -> raise e 79 + | `Closed 80 + | `Read_closed _ -> raise End_of_file 81 + | _ -> 82 + match Flow.single_read t.flow t.recv_buf with 83 + | exception End_of_file -> 84 + t.state <- half_close t.state `read; 85 + raise End_of_file 86 + | exception exn -> 87 + (match t.state with 88 + | `Error _ -> () 89 + | _ -> t.state <- `Error exn) ; 90 + raise exn 91 + | n -> 92 + match t.state with 93 + | `Error e -> raise e 94 + | `Active tls | `Read_closed tls | `Write_closed tls -> 95 + handle tls (Cstruct.to_string t.recv_buf ~off:0 ~len:n) 96 + | `Closed -> raise End_of_file 97 + 98 + let rec single_read t buf = 99 + 100 + let writeout res = 101 + let open Cstruct in 102 + let rlen = length res in 103 + let n = min (length buf) rlen in 104 + blit res 0 buf 0 n ; 105 + t.linger <- 106 + (if n < rlen then Some (sub res n (rlen - n)) else None) ; 107 + n in 108 + 109 + match t.linger with 110 + | Some res -> writeout res 111 + | None -> 112 + match read_react t with 113 + | None -> single_read t buf 114 + | Some res -> writeout res 115 + 116 + let writev t css = 117 + match t.state with 118 + | `Error err -> raise err 119 + | `Write_closed _ | `Closed -> raise (Eio.Net.err (Connection_reset Tls_socket_closed)) 120 + | `Active tls | `Read_closed tls -> 121 + let css = List.map Cstruct.to_string css in 122 + match Tls.Engine.send_application_data tls css with 123 + | Some (tls, tlsdata) -> 124 + ( t.state <- inject_state tls t.state ; write_t t tlsdata ) 125 + | None -> invalid_arg "tls: write: socket not ready" 126 + 127 + let single_write t bufs = 128 + writev t bufs; 129 + Cstruct.lenv bufs 130 + 131 + (* 132 + * XXX bad XXX 133 + * This is a point that should particularly be protected from concurrent r/w. 134 + * Doing this before a `t` is returned is safe; redoing it during rekeying is 135 + * not, as the API client already sees the `t` and can mistakenly interleave 136 + * writes while this is in progress. 137 + * *) 138 + let rec drain_handshake t = 139 + let push_linger t mcs = 140 + match (mcs, t.linger) with 141 + | (None, _) -> () 142 + | (scs, None) -> t.linger <- scs 143 + | (Some cs, Some l) -> t.linger <- Some (Cstruct.append l cs) 144 + in 145 + match t.state with 146 + | `Active tls when not (Tls.Engine.handshake_in_progress tls) -> 147 + t 148 + | _ -> 149 + let cs = read_react t in 150 + push_linger t cs; drain_handshake t 151 + 152 + let reneg ?authenticator ?acceptable_cas ?cert ?(drop = true) t = 153 + match t.state with 154 + | `Error err -> raise err 155 + | `Closed | `Read_closed _ | `Write_closed _ -> invalid_arg "tls: closed socket" 156 + | `Active tls -> 157 + match Tls.Engine.reneg ?authenticator ?acceptable_cas ?cert tls with 158 + | None -> invalid_arg "tls: can't renegotiate" 159 + | Some (tls', buf) -> 160 + if drop then t.linger <- None ; 161 + t.state <- inject_state tls' t.state ; 162 + write_t t buf; 163 + ignore (drain_handshake t : t) 164 + 165 + let key_update ?request t = 166 + match t.state with 167 + | `Error err -> raise err 168 + | `Write_closed _ | `Closed -> invalid_arg "tls: closed socket" 169 + | `Active tls | `Read_closed tls -> 170 + match Tls.Engine.key_update ?request tls with 171 + | Error f -> Fmt.invalid_arg "tls: can't update key: %a" Tls.Engine.pp_failure f 172 + | Ok (tls', buf) -> 173 + t.state <- inject_state tls' t.state ; 174 + write_t t buf 175 + 176 + let shutdown t = function 177 + | `Receive -> () 178 + | `Send | `All -> 179 + match t.state with 180 + | `Active tls | `Read_closed tls -> 181 + let tls', buf = Tls.Engine.send_close_notify tls in 182 + t.state <- inject_state tls' (half_close t.state `write) ; 183 + write_t t buf 184 + | _ -> () 185 + 186 + let server_of_flow config flow = 187 + drain_handshake { 188 + state = `Active (Tls.Engine.server config) ; 189 + flow = (flow :> [Flow.two_way_ty | Eio.Resource.close_ty] r) ; 190 + linger = None ; 191 + recv_buf = Cstruct.create 4096 192 + } 193 + 194 + let client_of_flow config ?host flow = 195 + let config' = match host with 196 + | None -> config 197 + | Some host -> Tls.Config.peer config host 198 + in 199 + let (tls, init) = Tls.Engine.client config' in 200 + let t = { 201 + state = `Active tls ; 202 + flow = (flow :> [Flow.two_way_ty | Eio.Resource.close_ty] r); 203 + linger = None ; 204 + recv_buf = Cstruct.create 4096 205 + } in 206 + write_t t init; 207 + drain_handshake t 208 + 209 + 210 + let epoch t = 211 + match t.state with 212 + | `Active tls | `Read_closed tls | `Write_closed tls -> Tls.Engine.epoch tls 213 + | `Closed | `Error _ -> Error () 214 + 215 + let copy t ~src = Eio.Flow.Pi.simple_copy ~single_write t ~src 216 + 217 + let read_methods = [] 218 + 219 + let close t = Eio.Resource.close t.flow 220 + 221 + type (_, _, _) Eio.Resource.pi += T : ('t, 't -> t, ty) Eio.Resource.pi 222 + end 223 + 224 + let raw (Eio.Resource.T (t, ops)) = Eio.Resource.get ops Raw.T t 225 + 226 + let handler = 227 + Eio.Resource.handler [ 228 + H (Eio.Flow.Pi.Source, (module Raw)); 229 + H (Eio.Flow.Pi.Sink, (module Raw)); 230 + H (Eio.Flow.Pi.Shutdown, (module Raw)); 231 + H (Eio.Resource.Close, Raw.close); 232 + H (Raw.T, Fun.id); 233 + ] 234 + 235 + let of_t t = Eio.Resource.T (t, handler) 236 + 237 + let server_of_flow config flow = Raw.server_of_flow config flow |> of_t 238 + let client_of_flow config ?host flow = Raw.client_of_flow config ?host flow |> of_t 239 + 240 + let reneg ?authenticator ?acceptable_cas ?cert ?drop (t:t) = Raw.reneg ?authenticator ?acceptable_cas ?cert ?drop (raw t) 241 + let key_update ?request (t:t) = Raw.key_update ?request (raw t) 242 + let epoch (t:t) = Raw.epoch (raw t) 243 + 244 + let () = 245 + Printexc.register_printer (function 246 + | Tls_alert typ -> 247 + Some ("TLS alert from peer: " ^ Tls.Packet.alert_type_to_string typ) 248 + | Tls_failure f -> 249 + Some ("TLS failure: " ^ Tls.Engine.string_of_failure f) 250 + | _ -> None)
+59
vendor/opam/tls/eio/tls_eio.mli
··· 1 + (** Effectful operations using Eio for pure TLS. 2 + 3 + The pure TLS is state and buffer in, state and buffer out. This 4 + module uses Eio for communication over the network. *) 5 + 6 + open Eio.Std 7 + 8 + (** [Tls_alert] exception received from the other endpoint *) 9 + exception Tls_alert of Tls.Packet.alert_type 10 + 11 + (** [Tls_failure] exception while processing incoming data *) 12 + exception Tls_failure of Tls.Engine.failure 13 + 14 + type t = [ `Tls | Eio.Flow.two_way_ty | Eio.Resource.close_ty ] r 15 + 16 + (** {2 Constructors} *) 17 + 18 + (** [server_of_flow server flow] is [t], after server-side TLS 19 + handshake of [flow] using [server] configuration. 20 + 21 + You must ensure a RNG is installed while using TLS, e.g. using [Mirage_crypto_rng_unix.use_default ()]. 22 + Ideally, this would be part of the [server] config so you couldn't forget it, 23 + but for now you'll get a runtime error if you forget. *) 24 + val server_of_flow : 25 + Tls.Config.server -> 26 + [> Eio.Flow.two_way_ty | Eio.Resource.close_ty] r -> t 27 + 28 + (** [client_of_flow client ~host fd] is [t], after client-side 29 + TLS handshake of [flow] using [client] configuration and [host]. 30 + 31 + You must ensure a RNG is installed while using TLS, e.g. using [Mirage_crypto_rng_unix.use_default ()]. 32 + Ideally, this would be part of the [client] config so you couldn't forget it, 33 + but for now you'll get a runtime error if you forget. *) 34 + val client_of_flow : 35 + Tls.Config.client -> ?host:[ `host ] Domain_name.t -> 36 + [> Eio.Flow.two_way_ty | Eio.Resource.close_ty] r -> t 37 + 38 + (** {2 Control of TLS features} *) 39 + 40 + (** [reneg ~authenticator ~acceptable_cas ~cert ~drop t] renegotiates the 41 + session, and blocks until the renegotiation finished. Optionally, a new 42 + [authenticator] and [acceptable_cas] can be used. The own certificate can 43 + be adjusted by [cert]. If [drop] is [true] (the default), 44 + application data received before the renegotiation finished is dropped. *) 45 + val reneg : 46 + ?authenticator:X509.Authenticator.t -> 47 + ?acceptable_cas:X509.Distinguished_name.t list -> 48 + ?cert:Tls.Config.own_cert -> 49 + ?drop:bool -> 50 + t -> unit 51 + 52 + (** [key_update ~request t] updates the traffic key and requests a traffic key 53 + update from the peer if [request] is provided and [true] (the default). 54 + This is only supported in TLS 1.3. *) 55 + val key_update : ?request:bool -> t -> unit 56 + 57 + (** [epoch t] returns [epoch], which contains information of the 58 + active session. *) 59 + val epoch : t -> (Tls.Core.epoch_data, unit) result
+89
vendor/opam/tls/eio/x509_eio.ml
··· 1 + open Eio.Std 2 + 3 + module Path = Eio.Path 4 + 5 + let (</>) = Path.( / ) 6 + 7 + let extension str = 8 + let n = String.length str in 9 + let rec scan = function 10 + | i when i = 0 -> None 11 + | i when str.[i - 1] = '.' -> 12 + Some (String.sub str i (n - i)) 13 + | i -> scan (pred i) in 14 + scan n 15 + 16 + 17 + let private_of_pems ~cert ~priv_key = 18 + let certs = 19 + try 20 + let pem = Path.load cert in 21 + match X509.Certificate.decode_pem_multiple pem with 22 + | Ok cs -> cs 23 + | Error (`Msg m) -> invalid_arg ("failed to parse certificates " ^ m) 24 + with Invalid_argument m -> 25 + Fmt.failwith "Private certificates %a: %s" Path.pp cert m 26 + in 27 + let pk = 28 + try 29 + let pem = Path.load priv_key in 30 + match X509.Private_key.decode_pem pem with 31 + | Ok key -> key 32 + | Error (`Msg m) -> invalid_arg ("failed to parse private key " ^ m) 33 + with Invalid_argument m -> 34 + Fmt.failwith "Private key (%a): %s" Path.pp priv_key m 35 + in 36 + (certs, pk) 37 + 38 + let certs_of_pem path = 39 + try 40 + let pem = Path.load path in 41 + match X509.Certificate.decode_pem_multiple pem with 42 + | Ok cs -> cs 43 + | Error (`Msg m) -> invalid_arg ("failed to parse certificates " ^ m) 44 + with Invalid_argument m -> 45 + Fmt.failwith "Certificates in %a: %s" Path.pp path m 46 + 47 + let certs_of_pem_dir path = 48 + Path.read_dir path 49 + |> List.filter (fun file -> extension file = Some "crt") 50 + |> Fiber.List.map (fun file -> certs_of_pem (path </> file)) 51 + |> List.concat 52 + 53 + let crl_of_pem path = 54 + try 55 + let data = Path.load path in 56 + match X509.CRL.decode_der data with 57 + | Ok cs -> cs 58 + | Error (`Msg m) -> invalid_arg ("failed to parse CRL " ^ m) 59 + with Invalid_argument m -> 60 + Fmt.failwith "CRL in %a: %s" Path.pp path m 61 + 62 + let crls_of_pem_dir path = 63 + Path.read_dir path 64 + |> Fiber.List.map (fun file -> crl_of_pem (path </> file)) 65 + 66 + (* Would be better to take an Eio.Time.clock here, but that API is likely to change soon. *) 67 + let authenticator ?allowed_hashes ?crls param = 68 + let time () = Some (Ptime_clock.now ()) in 69 + let of_cas cas = 70 + let crls = Option.map crls_of_pem_dir crls in 71 + X509.Authenticator.chain_of_trust ?allowed_hashes ?crls ~time cas 72 + and dotted_hex_to_cs hex = 73 + Cstruct.to_string (Cstruct.of_hex (String.map (function ':' -> ' ' | x -> x) hex)) 74 + and fingerp hash fingerprint = 75 + X509.Authenticator.key_fingerprint ~time ~hash ~fingerprint 76 + and cert_fingerp hash fingerprint = 77 + X509.Authenticator.cert_fingerprint ~time ~hash ~fingerprint 78 + in 79 + match param with 80 + | `Ca_file path -> certs_of_pem path |> of_cas 81 + | `Ca_dir path -> certs_of_pem_dir path |> of_cas 82 + | `Key_fingerprint (hash, fp) -> fingerp hash fp 83 + | `Hex_key_fingerprint (hash, fp) -> 84 + let fp = dotted_hex_to_cs fp in 85 + fingerp hash fp 86 + | `Cert_fingerprint (hash, fp) -> cert_fingerp hash fp 87 + | `Hex_cert_fingerprint (hash, fp) -> 88 + let fp = dotted_hex_to_cs fp in 89 + cert_fingerp hash fp
+26
vendor/opam/tls/eio/x509_eio.mli
··· 1 + (** X.509 certificate handling using Eio. *) 2 + 3 + (** [private_of_pems ~cert ~priv_key] is [priv], after reading the 4 + private key and certificate chain from the given PEM-encoded 5 + files. *) 6 + val private_of_pems : cert:_ Eio.Path.t -> priv_key:_ Eio.Path.t -> Tls.Config.certchain 7 + 8 + (** [certs_of_pem file] is [certificates], which are read from the 9 + PEM-encoded [file]. *) 10 + val certs_of_pem : _ Eio.Path.t -> X509.Certificate.t list 11 + 12 + (** [certs_of_pem_dir dir] is [certificates], which are read from all 13 + PEM-encoded files in [dir]. *) 14 + val certs_of_pem_dir : _ Eio.Path.t -> X509.Certificate.t list 15 + 16 + (** [authenticator methods] constructs an [authenticator] using the 17 + specified method and data. *) 18 + val authenticator : ?allowed_hashes:Digestif.hash' list -> ?crls:_ Eio.Path.t -> 19 + [ `Ca_file of _ Eio.Path.t 20 + | `Ca_dir of _ Eio.Path.t 21 + | `Key_fingerprint of Digestif.hash' * string 22 + | `Hex_key_fingerprint of Digestif.hash' * string 23 + | `Cert_fingerprint of Digestif.hash' * string 24 + | `Hex_cert_fingerprint of Digestif.hash' * string 25 + ] 26 + -> X509.Authenticator.t
+366
vendor/opam/tls/lib/ciphersuite.ml
··· 1 + (** Ciphersuite definitions and some helper functions. *) 2 + 3 + (** sum type of all possible key exchange methods *) 4 + type key_exchange_algorithm_dhe = [ `FFDHE | `ECDHE ] 5 + type key_exchange_algorithm = [ key_exchange_algorithm_dhe | `RSA ] 6 + 7 + let pp_key_exchange_algorithm_dhe ppf = function 8 + | `FFDHE -> Fmt.string ppf "FFDHE" 9 + | `ECDHE -> Fmt.string ppf "ECDHE" 10 + 11 + let pp_key_exchange_algorithm ppf = function 12 + | #key_exchange_algorithm_dhe as d -> pp_key_exchange_algorithm_dhe ppf d 13 + | `RSA -> Fmt.string ppf "RSA" 14 + 15 + (** [required_usage kex] is [usage] which a certificate must have if it is used in the given [kex] method *) 16 + let required_usage = function 17 + | #key_exchange_algorithm_dhe -> `Digital_signature 18 + | `RSA -> `Key_encipherment 19 + 20 + type block_cipher = 21 + | TRIPLE_DES_EDE_CBC 22 + | AES_128_CBC 23 + | AES_256_CBC 24 + 25 + let pp_block_cipher ppf = function 26 + | TRIPLE_DES_EDE_CBC -> Fmt.string ppf "3DES EDE CBC" 27 + | AES_128_CBC -> Fmt.string ppf "AES128 CBC" 28 + | AES_256_CBC -> Fmt.string ppf "AES256 CBC" 29 + 30 + type aead_cipher = 31 + | AES_128_CCM 32 + | AES_256_CCM 33 + | AES_128_GCM 34 + | AES_256_GCM 35 + | CHACHA20_POLY1305 36 + 37 + let pp_aead_cipher ppf = function 38 + | AES_128_CCM -> Fmt.string ppf "AES128 CCM" 39 + | AES_256_CCM -> Fmt.string ppf "AES256 CCM" 40 + | AES_128_GCM -> Fmt.string ppf "AES128 GCM" 41 + | AES_256_GCM -> Fmt.string ppf "AES256 GCM" 42 + | CHACHA20_POLY1305 -> Fmt.string ppf "CHACHA20 POLY1305" 43 + 44 + type payload_protection13 = [ `AEAD of aead_cipher ] 45 + 46 + let pp_payload_protection13 ppf = function 47 + | `AEAD a -> Fmt.pf ppf "AEAD %a" pp_aead_cipher a 48 + 49 + type payload_protection = [ 50 + payload_protection13 51 + | `Block of block_cipher * Digestif.hash' 52 + ] 53 + 54 + let pp_hash ppf = function 55 + | `MD5 -> Fmt.string ppf "MD5" 56 + | `SHA1 -> Fmt.string ppf "SHA1" 57 + | `SHA224 -> Fmt.string ppf "SHA224" 58 + | `SHA256 -> Fmt.string ppf "SHA256" 59 + | `SHA384 -> Fmt.string ppf "SHA384" 60 + | `SHA512 -> Fmt.string ppf "SHA512" 61 + 62 + let pp_payload_protection ppf = function 63 + | #payload_protection13 as p -> pp_payload_protection13 ppf p 64 + | `Block (b, h) -> Fmt.pf ppf "BLOCK %a %a" pp_block_cipher b pp_hash h 65 + 66 + (* this is K_LEN, max 8 N_MIN from RFC5116 sections 5.1 & 5.2 -- as defined in TLS1.3 RFC 8446 Section 5.3 *) 67 + let kn_13 = function 68 + | AES_128_GCM -> (16, 12) 69 + | AES_256_GCM -> (32, 12) 70 + | AES_128_CCM -> (16, 12) 71 + | AES_256_CCM -> (32, 12) 72 + | CHACHA20_POLY1305 -> (32, 12) 73 + 74 + (** [key_length iv payload_protection] is [(key size, IV size, mac size)] where key IV, and mac sizes are the required bytes for the given [payload_protection] *) 75 + (* NB only used for <= TLS 1.2, IV length for AEAD defined in RFC 5288 Section 3 (for GCM), salt[4] for CCM in RFC 6655 Section 3 *) 76 + let key_length iv pp = 77 + let mac_size m = 78 + let module H = (val Digestif.module_of_hash' m) in 79 + H.digest_size 80 + in 81 + match pp with 82 + | `AEAD AES_128_CCM -> (16, 4 , 0) 83 + | `AEAD AES_256_CCM -> (32, 4 , 0) 84 + | `AEAD AES_128_GCM -> (16, 4 , 0) 85 + | `AEAD AES_256_GCM -> (32, 4 , 0) 86 + | `AEAD CHACHA20_POLY1305 -> (32, 12, 0) 87 + | `Block (bc, mac) -> 88 + let keylen, ivlen = match bc with 89 + | TRIPLE_DES_EDE_CBC -> (24, 8) 90 + | AES_128_CBC -> (16, 16) 91 + | AES_256_CBC -> (32, 16) 92 + and maclen = mac_size mac 93 + in 94 + match iv with 95 + | None -> (keylen, 0, maclen) 96 + | Some () -> (keylen, ivlen, maclen) 97 + 98 + type ciphersuite13 = [ 99 + | `AES_128_GCM_SHA256 100 + | `AES_256_GCM_SHA384 101 + | `CHACHA20_POLY1305_SHA256 102 + | `AES_128_CCM_SHA256 103 + ] 104 + 105 + let privprot13 = function 106 + | `AES_128_GCM_SHA256 -> AES_128_GCM 107 + | `AES_256_GCM_SHA384 -> AES_256_GCM 108 + | `CHACHA20_POLY1305_SHA256 -> CHACHA20_POLY1305 109 + | `AES_128_CCM_SHA256 -> AES_128_CCM 110 + 111 + let hash13 = function 112 + | `AES_128_GCM_SHA256 -> `SHA256 113 + | `AES_256_GCM_SHA384 -> `SHA384 114 + | `CHACHA20_POLY1305_SHA256 -> `SHA256 115 + | `AES_128_CCM_SHA256 -> `SHA256 116 + 117 + let any_ciphersuite_to_ciphersuite13 = function 118 + | Packet.TLS_AES_128_GCM_SHA256 -> Some `AES_128_GCM_SHA256 119 + | Packet.TLS_AES_256_GCM_SHA384 -> Some `AES_256_GCM_SHA384 120 + | Packet.TLS_CHACHA20_POLY1305_SHA256 -> Some `CHACHA20_POLY1305_SHA256 121 + | Packet.TLS_AES_128_CCM_SHA256 -> Some `AES_128_CCM_SHA256 122 + | _ -> None 123 + 124 + type ciphersuite = [ 125 + ciphersuite13 126 + | `DHE_RSA_WITH_AES_128_GCM_SHA256 127 + | `DHE_RSA_WITH_AES_256_GCM_SHA384 128 + | `DHE_RSA_WITH_AES_256_CCM 129 + | `DHE_RSA_WITH_AES_128_CCM 130 + | `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 131 + | `DHE_RSA_WITH_AES_256_CBC_SHA256 132 + | `DHE_RSA_WITH_AES_128_CBC_SHA256 133 + | `DHE_RSA_WITH_AES_256_CBC_SHA 134 + | `DHE_RSA_WITH_AES_128_CBC_SHA 135 + | `DHE_RSA_WITH_3DES_EDE_CBC_SHA 136 + | `ECDHE_RSA_WITH_AES_128_GCM_SHA256 137 + | `ECDHE_RSA_WITH_AES_256_GCM_SHA384 138 + | `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 139 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA384 140 + | `ECDHE_RSA_WITH_AES_128_CBC_SHA256 141 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA 142 + | `ECDHE_RSA_WITH_AES_128_CBC_SHA 143 + | `ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 144 + | `RSA_WITH_AES_256_CBC_SHA256 145 + | `RSA_WITH_AES_128_CBC_SHA256 146 + | `RSA_WITH_AES_256_CBC_SHA 147 + | `RSA_WITH_AES_128_CBC_SHA 148 + | `RSA_WITH_3DES_EDE_CBC_SHA 149 + | `RSA_WITH_AES_128_GCM_SHA256 150 + | `RSA_WITH_AES_256_GCM_SHA384 151 + | `RSA_WITH_AES_256_CCM 152 + | `RSA_WITH_AES_128_CCM 153 + | `ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 154 + | `ECDHE_ECDSA_WITH_AES_128_CBC_SHA 155 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA 156 + | `ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 157 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 158 + | `ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 159 + | `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 160 + | `ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 161 + ] 162 + 163 + let ciphersuite_to_ciphersuite13 : ciphersuite -> ciphersuite13 option = function 164 + | #ciphersuite13 as cs -> Some cs 165 + | _ -> None 166 + 167 + let any_ciphersuite_to_ciphersuite = function 168 + | Packet.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 -> Some `DHE_RSA_WITH_AES_256_CBC_SHA256 169 + | Packet.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 -> Some `DHE_RSA_WITH_AES_128_CBC_SHA256 170 + | Packet.TLS_DHE_RSA_WITH_AES_256_CBC_SHA -> Some `DHE_RSA_WITH_AES_256_CBC_SHA 171 + | Packet.TLS_DHE_RSA_WITH_AES_128_CBC_SHA -> Some `DHE_RSA_WITH_AES_128_CBC_SHA 172 + | Packet.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA -> Some `DHE_RSA_WITH_3DES_EDE_CBC_SHA 173 + | Packet.TLS_RSA_WITH_AES_256_CBC_SHA256 -> Some `RSA_WITH_AES_256_CBC_SHA256 174 + | Packet.TLS_RSA_WITH_AES_128_CBC_SHA256 -> Some `RSA_WITH_AES_128_CBC_SHA256 175 + | Packet.TLS_RSA_WITH_AES_256_CBC_SHA -> Some `RSA_WITH_AES_256_CBC_SHA 176 + | Packet.TLS_RSA_WITH_AES_128_CBC_SHA -> Some `RSA_WITH_AES_128_CBC_SHA 177 + | Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA -> Some `RSA_WITH_3DES_EDE_CBC_SHA 178 + | Packet.TLS_RSA_WITH_AES_128_CCM -> Some `RSA_WITH_AES_128_CCM 179 + | Packet.TLS_RSA_WITH_AES_256_CCM -> Some `RSA_WITH_AES_256_CCM 180 + | Packet.TLS_DHE_RSA_WITH_AES_128_CCM -> Some `DHE_RSA_WITH_AES_128_CCM 181 + | Packet.TLS_DHE_RSA_WITH_AES_256_CCM -> Some `DHE_RSA_WITH_AES_256_CCM 182 + | Packet.TLS_RSA_WITH_AES_128_GCM_SHA256 -> Some `RSA_WITH_AES_128_GCM_SHA256 183 + | Packet.TLS_RSA_WITH_AES_256_GCM_SHA384 -> Some `RSA_WITH_AES_256_GCM_SHA384 184 + | Packet.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 -> Some `DHE_RSA_WITH_AES_128_GCM_SHA256 185 + | Packet.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 -> Some `DHE_RSA_WITH_AES_256_GCM_SHA384 186 + | Packet.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -> Some `ECDHE_RSA_WITH_AES_128_GCM_SHA256 187 + | Packet.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -> Some `ECDHE_RSA_WITH_AES_256_GCM_SHA384 188 + | Packet.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 -> Some `ECDHE_RSA_WITH_AES_256_CBC_SHA384 189 + | Packet.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 -> Some `ECDHE_RSA_WITH_AES_128_CBC_SHA256 190 + | Packet.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA -> Some `ECDHE_RSA_WITH_AES_256_CBC_SHA 191 + | Packet.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA -> Some `ECDHE_RSA_WITH_AES_128_CBC_SHA 192 + | Packet.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA -> Some `ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 193 + | Packet.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> Some `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 194 + | Packet.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> Some `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 195 + | Packet.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA -> Some `ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 196 + | Packet.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA -> Some `ECDHE_ECDSA_WITH_AES_128_CBC_SHA 197 + | Packet.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA -> Some `ECDHE_ECDSA_WITH_AES_256_CBC_SHA 198 + | Packet.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 -> Some `ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 199 + | Packet.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 -> Some `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 200 + | Packet.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -> Some `ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 201 + | Packet.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -> Some `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 202 + | Packet.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -> Some `ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 203 + | x -> any_ciphersuite_to_ciphersuite13 x 204 + 205 + let ciphersuite_to_any_ciphersuite = function 206 + | `DHE_RSA_WITH_AES_256_CBC_SHA256 -> Packet.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 207 + | `DHE_RSA_WITH_AES_128_CBC_SHA256 -> Packet.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 208 + | `DHE_RSA_WITH_AES_256_CBC_SHA -> Packet.TLS_DHE_RSA_WITH_AES_256_CBC_SHA 209 + | `DHE_RSA_WITH_AES_128_CBC_SHA -> Packet.TLS_DHE_RSA_WITH_AES_128_CBC_SHA 210 + | `DHE_RSA_WITH_3DES_EDE_CBC_SHA -> Packet.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 211 + | `RSA_WITH_AES_256_CBC_SHA256 -> Packet.TLS_RSA_WITH_AES_256_CBC_SHA256 212 + | `RSA_WITH_AES_128_CBC_SHA256 -> Packet.TLS_RSA_WITH_AES_128_CBC_SHA256 213 + | `RSA_WITH_AES_256_CBC_SHA -> Packet.TLS_RSA_WITH_AES_256_CBC_SHA 214 + | `RSA_WITH_AES_128_CBC_SHA -> Packet.TLS_RSA_WITH_AES_128_CBC_SHA 215 + | `RSA_WITH_3DES_EDE_CBC_SHA -> Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA 216 + | `RSA_WITH_AES_128_CCM -> Packet.TLS_RSA_WITH_AES_128_CCM 217 + | `RSA_WITH_AES_256_CCM -> Packet.TLS_RSA_WITH_AES_256_CCM 218 + | `DHE_RSA_WITH_AES_128_CCM -> Packet.TLS_DHE_RSA_WITH_AES_128_CCM 219 + | `DHE_RSA_WITH_AES_256_CCM -> Packet.TLS_DHE_RSA_WITH_AES_256_CCM 220 + | `RSA_WITH_AES_128_GCM_SHA256 -> Packet.TLS_RSA_WITH_AES_128_GCM_SHA256 221 + | `RSA_WITH_AES_256_GCM_SHA384 -> Packet.TLS_RSA_WITH_AES_256_GCM_SHA384 222 + | `DHE_RSA_WITH_AES_128_GCM_SHA256 -> Packet.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 223 + | `DHE_RSA_WITH_AES_256_GCM_SHA384 -> Packet.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 224 + | `ECDHE_RSA_WITH_AES_128_GCM_SHA256 -> Packet.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 225 + | `ECDHE_RSA_WITH_AES_256_GCM_SHA384 -> Packet.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 226 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA384 -> Packet.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 227 + | `ECDHE_RSA_WITH_AES_128_CBC_SHA256 -> Packet.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 228 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA -> Packet.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 229 + | `ECDHE_RSA_WITH_AES_128_CBC_SHA -> Packet.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 230 + | `ECDHE_RSA_WITH_3DES_EDE_CBC_SHA -> Packet.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 231 + | `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> Packet.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 232 + | `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> Packet.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 233 + | `AES_128_GCM_SHA256 -> Packet.TLS_AES_128_GCM_SHA256 234 + | `AES_256_GCM_SHA384 -> Packet.TLS_AES_256_GCM_SHA384 235 + | `CHACHA20_POLY1305_SHA256 -> Packet.TLS_CHACHA20_POLY1305_SHA256 236 + | `AES_128_CCM_SHA256 -> Packet.TLS_AES_128_CCM_SHA256 237 + | `ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA -> Packet.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 238 + | `ECDHE_ECDSA_WITH_AES_128_CBC_SHA -> Packet.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 239 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA -> Packet.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 240 + | `ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 -> Packet.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 241 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 -> Packet.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 242 + | `ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -> Packet.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 243 + | `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -> Packet.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 244 + | `ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -> Packet.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 245 + 246 + (** [get_kex_privprot ciphersuite] is [(kex, privacy_protection)] where it dissects the [ciphersuite] into a pair containing the key exchange method [kex], and its [privacy_protection] *) 247 + let get_keytype_kex_privprot = function 248 + | `RSA_WITH_3DES_EDE_CBC_SHA -> (`RSA, `RSA, `Block (TRIPLE_DES_EDE_CBC, `SHA1)) 249 + | `DHE_RSA_WITH_3DES_EDE_CBC_SHA -> (`RSA, `FFDHE, `Block (TRIPLE_DES_EDE_CBC, `SHA1)) 250 + | `RSA_WITH_AES_128_CBC_SHA -> (`RSA, `RSA, `Block (AES_128_CBC, `SHA1)) 251 + | `DHE_RSA_WITH_AES_128_CBC_SHA -> (`RSA, `FFDHE, `Block (AES_128_CBC, `SHA1)) 252 + | `RSA_WITH_AES_256_CBC_SHA -> (`RSA, `RSA, `Block (AES_256_CBC, `SHA1)) 253 + | `DHE_RSA_WITH_AES_256_CBC_SHA -> (`RSA, `FFDHE, `Block (AES_256_CBC, `SHA1)) 254 + | `RSA_WITH_AES_128_CBC_SHA256 -> (`RSA, `RSA, `Block (AES_128_CBC, `SHA256)) 255 + | `RSA_WITH_AES_256_CBC_SHA256 -> (`RSA, `RSA, `Block (AES_256_CBC, `SHA256)) 256 + | `DHE_RSA_WITH_AES_128_CBC_SHA256 -> (`RSA, `FFDHE, `Block (AES_128_CBC, `SHA256)) 257 + | `DHE_RSA_WITH_AES_256_CBC_SHA256 -> (`RSA, `FFDHE, `Block (AES_256_CBC, `SHA256)) 258 + | `RSA_WITH_AES_128_CCM -> (`RSA, `RSA, `AEAD AES_128_CCM) 259 + | `RSA_WITH_AES_256_CCM -> (`RSA, `RSA, `AEAD AES_256_CCM) 260 + | `DHE_RSA_WITH_AES_128_CCM -> (`RSA, `FFDHE, `AEAD AES_128_CCM) 261 + | `DHE_RSA_WITH_AES_256_CCM -> (`RSA, `FFDHE, `AEAD AES_256_CCM) 262 + | `RSA_WITH_AES_128_GCM_SHA256 -> (`RSA, `RSA, `AEAD AES_128_GCM) 263 + | `RSA_WITH_AES_256_GCM_SHA384 -> (`RSA, `RSA, `AEAD AES_256_GCM) 264 + | `DHE_RSA_WITH_AES_128_GCM_SHA256 -> (`RSA, `FFDHE, `AEAD AES_128_GCM) 265 + | `DHE_RSA_WITH_AES_256_GCM_SHA384 -> (`RSA, `FFDHE, `AEAD AES_256_GCM) 266 + | `ECDHE_RSA_WITH_AES_128_GCM_SHA256 -> (`RSA, `ECDHE, `AEAD AES_128_GCM) 267 + | `ECDHE_RSA_WITH_AES_256_GCM_SHA384 -> (`RSA, `ECDHE, `AEAD AES_256_GCM) 268 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA384 -> (`RSA, `ECDHE, `Block (AES_256_CBC, `SHA384)) 269 + | `ECDHE_RSA_WITH_AES_128_CBC_SHA256 -> (`RSA, `ECDHE, `Block (AES_128_CBC, `SHA256)) 270 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA -> (`RSA, `ECDHE, `Block (AES_256_CBC, `SHA1)) 271 + | `ECDHE_RSA_WITH_AES_128_CBC_SHA -> (`RSA, `ECDHE, `Block (AES_128_CBC, `SHA1)) 272 + | `ECDHE_RSA_WITH_3DES_EDE_CBC_SHA -> (`RSA, `ECDHE, `Block (TRIPLE_DES_EDE_CBC, `SHA1)) 273 + | `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> (`RSA, `FFDHE, `AEAD CHACHA20_POLY1305) 274 + | `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> (`RSA, `ECDHE, `AEAD CHACHA20_POLY1305) 275 + | `ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA -> (`EC, `ECDHE, `Block (TRIPLE_DES_EDE_CBC, `SHA1)) 276 + | `ECDHE_ECDSA_WITH_AES_128_CBC_SHA -> (`EC, `ECDHE, `Block (AES_128_CBC, `SHA1)) 277 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA -> (`EC, `ECDHE, `Block (AES_256_CBC, `SHA1)) 278 + | `ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 -> (`EC, `ECDHE, `Block (AES_128_CBC, `SHA256)) 279 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 -> (`EC, `ECDHE, `Block (AES_256_CBC, `SHA384)) 280 + | `ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -> (`EC, `ECDHE, `AEAD AES_128_GCM) 281 + | `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -> (`EC, `ECDHE, `AEAD AES_256_GCM) 282 + | `ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -> (`EC, `ECDHE, `AEAD CHACHA20_POLY1305) 283 + | #ciphersuite13 as cs13 -> (`RSA, `FFDHE, `AEAD (privprot13 cs13)) (* this is mostly wrong *) 284 + 285 + (** [ciphersuite_kex ciphersuite] is [kex], first projection of [get_kex_privprot] *) 286 + let ciphersuite_kex c = 287 + let _keytype, kex, _pp = get_keytype_kex_privprot c in 288 + kex 289 + 290 + (** [ciphersuite_privprot ciphersuite] is [privprot], second projection of [get_kex_privprot] *) 291 + let ciphersuite_privprot c = 292 + let _keytype, _kex, pp = get_keytype_kex_privprot c in 293 + pp 294 + 295 + let ciphersuite_keytype c = 296 + let keytype, _kex, _pp = get_keytype_kex_privprot c in 297 + keytype 298 + 299 + let pp_ciphersuite ppf cs = 300 + let keytype, kex, pp = get_keytype_kex_privprot cs in 301 + let pp_keytype ppf = function 302 + | `EC -> Fmt.string ppf "ECDSA" 303 + | `RSA -> Fmt.string ppf "RSA" 304 + in 305 + match cs with 306 + | #ciphersuite13 -> Fmt.pf ppf "%a" pp_payload_protection pp 307 + | _ -> Fmt.pf ppf "%a %a %a" pp_key_exchange_algorithm kex pp_keytype keytype 308 + pp_payload_protection pp 309 + 310 + let pp_any_ciphersuite ppf cs = 311 + match any_ciphersuite_to_ciphersuite cs with 312 + | Some cs -> pp_ciphersuite ppf cs 313 + | None -> Fmt.pf ppf "ciphersuite %04X" (Packet.any_ciphersuite_to_int cs) 314 + 315 + let ciphersuite_fs cs = 316 + match ciphersuite_kex cs with 317 + | #key_exchange_algorithm_dhe -> true 318 + | `RSA -> false 319 + 320 + let ecdhe_only = function 321 + | #ciphersuite13 -> false 322 + | cs -> match get_keytype_kex_privprot cs with 323 + | (_, `ECDHE, _) -> true 324 + | _ -> false 325 + 326 + let dhe_only = function 327 + | #ciphersuite13 -> false 328 + | cs -> match get_keytype_kex_privprot cs with 329 + | (_, `FFDHE, _) -> true 330 + | _ -> false 331 + 332 + let ecdhe = function 333 + | #ciphersuite13 -> true 334 + | cs -> match get_keytype_kex_privprot cs with 335 + | (_, `ECDHE, _) -> true 336 + | _ -> false 337 + 338 + let ciphersuite_tls12_only = function 339 + | `DHE_RSA_WITH_AES_256_CBC_SHA256 340 + | `DHE_RSA_WITH_AES_128_CBC_SHA256 341 + | `RSA_WITH_AES_256_CBC_SHA256 342 + | `RSA_WITH_AES_128_CBC_SHA256 343 + | `RSA_WITH_AES_128_CCM 344 + | `RSA_WITH_AES_256_CCM 345 + | `DHE_RSA_WITH_AES_128_CCM 346 + | `DHE_RSA_WITH_AES_256_CCM 347 + | `RSA_WITH_AES_128_GCM_SHA256 348 + | `RSA_WITH_AES_256_GCM_SHA384 349 + | `DHE_RSA_WITH_AES_128_GCM_SHA256 350 + | `DHE_RSA_WITH_AES_256_GCM_SHA384 351 + | `ECDHE_RSA_WITH_AES_128_GCM_SHA256 352 + | `ECDHE_RSA_WITH_AES_256_GCM_SHA384 353 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA384 354 + | `ECDHE_RSA_WITH_AES_128_CBC_SHA256 355 + | `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 356 + | `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 357 + | `ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 358 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 359 + | `ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 360 + | `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 361 + | `ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -> true 362 + | _ -> false 363 + 364 + let ciphersuite_tls13 = function 365 + | #ciphersuite13 -> true 366 + | _ -> false
+643
vendor/opam/tls/lib/config.ml
··· 1 + open Core 2 + 3 + let src = Logs.Src.create "tls.config" ~doc:"TLS config" 4 + module Log = (val Logs.src_log src : Logs.LOG) 5 + 6 + type certchain = X509.Certificate.t list * X509.Private_key.t 7 + 8 + type own_cert = [ 9 + | `None 10 + | `Single of certchain 11 + | `Multiple of certchain list 12 + | `Multiple_default of certchain * certchain list 13 + ] 14 + 15 + let pp_cert ppf cs = 16 + let from, until = X509.Certificate.validity cs in 17 + Fmt.pf ppf "subject %a@ issuer %a@ valid from %a until %a" 18 + X509.Distinguished_name.pp (X509.Certificate.subject cs) 19 + X509.Distinguished_name.pp (X509.Certificate.issuer cs) 20 + (Ptime.pp_human ~tz_offset_s:0 ()) from 21 + (Ptime.pp_human ~tz_offset_s:0 ()) until 22 + 23 + let pp_certchain ppf (chain, _) = 24 + Fmt.(list ~sep:(any "@.") pp_cert) ppf chain 25 + 26 + let pp_own_cert ppf = function 27 + | `None -> Fmt.string ppf "NONE" 28 + | `Single chain -> pp_certchain ppf chain 29 + | `Multiple cs -> 30 + Fmt.pf ppf "multiple: %a" Fmt.(list ~sep:(any "@.@.") pp_certchain) cs 31 + | `Multiple_default (c, cs) -> 32 + Fmt.pf ppf "multiple default:@.%a@.others:@.%a" 33 + pp_certchain c 34 + Fmt.(list ~sep:(any "@.@.") pp_certchain) cs 35 + 36 + type session_cache = SessionID.t -> epoch_data option 37 + 38 + type ticket_cache = { 39 + lookup : string -> (psk13 * epoch_data) option ; 40 + ticket_granted : psk13 -> epoch_data -> unit ; 41 + lifetime : int32 ; 42 + timestamp : unit -> Ptime.t 43 + } 44 + 45 + (* TODO: min_rsa, min_dh *) 46 + type config = { 47 + ciphers : Ciphersuite.ciphersuite list ; 48 + protocol_versions : tls_version * tls_version ; 49 + signature_algorithms : signature_algorithm list ; 50 + use_reneg : bool ; 51 + authenticator : X509.Authenticator.t option ; 52 + peer_name : [`host] Domain_name.t option ; 53 + own_certificates : own_cert ; 54 + acceptable_cas : X509.Distinguished_name.t list ; 55 + session_cache : session_cache ; 56 + ticket_cache : ticket_cache option ; 57 + cached_session : epoch_data option ; 58 + cached_ticket : (psk13 * epoch_data) option ; 59 + alpn_protocols : string list ; 60 + groups : group list ; 61 + zero_rtt : int32 ; 62 + ip : Ipaddr.t option ; 63 + } 64 + 65 + let pp_config ppf cfg = 66 + Fmt.pf ppf 67 + "ciphers: %a@. \ 68 + minimal protocol version: %a@. \ 69 + maximum protocol version: %a@. \ 70 + signature algorithms: %a@. \ 71 + renegotiation enabled %B@. \ 72 + peer name: %a@. \ 73 + own certificate: %a@. \ 74 + acceptable CAs: %a@. \ 75 + alpn protocols: %a@. \ 76 + groups: %a@. \ 77 + IP: %a@." 78 + Fmt.(list ~sep:(any ", ") Ciphersuite.pp_ciphersuite) cfg.ciphers 79 + pp_tls_version (fst cfg.protocol_versions) 80 + pp_tls_version (snd cfg.protocol_versions) 81 + Fmt.(list ~sep:(any ", ") pp_signature_algorithm) cfg.signature_algorithms 82 + cfg.use_reneg 83 + Fmt.(option ~none:(any "none provided") Domain_name.pp) cfg.peer_name 84 + pp_own_cert cfg.own_certificates 85 + Fmt.(list ~sep:(any ", ") X509.Distinguished_name.pp) cfg.acceptable_cas 86 + Fmt.(list ~sep:(any ", ") string) cfg.alpn_protocols 87 + Fmt.(list ~sep:(any ", ") pp_group) cfg.groups 88 + Fmt.(option ~none:(any "none provided") Ipaddr.pp) cfg.ip 89 + 90 + let ciphers13 cfg = 91 + List.rev 92 + (List.fold_left (fun acc cs -> 93 + match Ciphersuite.ciphersuite_to_ciphersuite13 cs with 94 + | None -> acc 95 + | Some c -> c :: acc) 96 + [] cfg.ciphers) 97 + 98 + module Ciphers = struct 99 + 100 + (* A good place for various pre-baked cipher lists and helper functions to 101 + * slice and groom those lists. *) 102 + 103 + let default13 = [ 104 + `AES_128_GCM_SHA256 ; 105 + `AES_256_GCM_SHA384 ; 106 + `CHACHA20_POLY1305_SHA256 ; 107 + `AES_128_CCM_SHA256 ; 108 + ] 109 + 110 + let default = default13 @ [ 111 + `DHE_RSA_WITH_AES_256_GCM_SHA384 ; 112 + `DHE_RSA_WITH_AES_128_GCM_SHA256 ; 113 + `DHE_RSA_WITH_AES_256_CCM ; 114 + `DHE_RSA_WITH_AES_128_CCM ; 115 + `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ; 116 + `ECDHE_RSA_WITH_AES_128_GCM_SHA256 ; 117 + `ECDHE_RSA_WITH_AES_256_GCM_SHA384 ; 118 + `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ; 119 + `ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ; 120 + `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ; 121 + `ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ; 122 + ] 123 + 124 + let supported = default @ [ 125 + `DHE_RSA_WITH_AES_256_CBC_SHA256 ; 126 + `DHE_RSA_WITH_AES_128_CBC_SHA256 ; 127 + `DHE_RSA_WITH_AES_256_CBC_SHA ; 128 + `DHE_RSA_WITH_AES_128_CBC_SHA ; 129 + `ECDHE_RSA_WITH_AES_256_CBC_SHA384 ; 130 + `ECDHE_RSA_WITH_AES_128_CBC_SHA256 ; 131 + `ECDHE_RSA_WITH_AES_256_CBC_SHA ; 132 + `ECDHE_RSA_WITH_AES_128_CBC_SHA ; 133 + `ECDHE_ECDSA_WITH_AES_128_CBC_SHA ; 134 + `ECDHE_ECDSA_WITH_AES_256_CBC_SHA ; 135 + `ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 ; 136 + `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 ; 137 + `RSA_WITH_AES_256_CBC_SHA256 ; 138 + `RSA_WITH_AES_128_CBC_SHA256 ; 139 + `RSA_WITH_AES_256_CBC_SHA ; 140 + `RSA_WITH_AES_128_CBC_SHA ; 141 + `RSA_WITH_AES_256_GCM_SHA384 ; 142 + `RSA_WITH_AES_128_GCM_SHA256 ; 143 + `RSA_WITH_AES_256_CCM ; 144 + `RSA_WITH_AES_128_CCM ; 145 + `DHE_RSA_WITH_3DES_EDE_CBC_SHA ; 146 + `RSA_WITH_3DES_EDE_CBC_SHA ; 147 + `ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA ; 148 + ] 149 + 150 + (* as defined in https://httpwg.org/specs/rfc7540.html#BadCipherSuites *) 151 + let http2 = default13 @ [ 152 + `DHE_RSA_WITH_AES_256_GCM_SHA384 ; 153 + `DHE_RSA_WITH_AES_128_GCM_SHA256 ; 154 + `DHE_RSA_WITH_AES_256_CCM ; 155 + `DHE_RSA_WITH_AES_128_CCM ; 156 + `DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ; 157 + `ECDHE_RSA_WITH_AES_128_GCM_SHA256 ; 158 + `ECDHE_RSA_WITH_AES_256_GCM_SHA384 ; 159 + `ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ; 160 + `ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ; 161 + `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ; 162 + `ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 ; 163 + ] 164 + 165 + let fs_of = List.filter Ciphersuite.ciphersuite_fs 166 + 167 + let fs = fs_of default 168 + end 169 + 170 + let default_signature_algorithms = 171 + [ `ECDSA_SECP256R1_SHA256 ; 172 + `ECDSA_SECP384R1_SHA384 ; 173 + `ECDSA_SECP521R1_SHA512 ; 174 + `ED25519 ; 175 + `RSA_PSS_RSAENC_SHA256 ; 176 + `RSA_PSS_RSAENC_SHA384 ; 177 + `RSA_PSS_RSAENC_SHA512 ; 178 + `RSA_PKCS1_SHA256 ; 179 + `RSA_PKCS1_SHA384 ; 180 + `RSA_PKCS1_SHA512 ; 181 + ] 182 + 183 + let supported_signature_algorithms = 184 + default_signature_algorithms @ [ 185 + `RSA_PKCS1_SHA224 ; 186 + `ECDSA_SECP256R1_SHA1 ; 187 + `RSA_PKCS1_SHA1 ; 188 + `RSA_PKCS1_MD5 189 + ] 190 + 191 + let min_dh_size = 1024 192 + 193 + let min_rsa_key_size = 1024 194 + 195 + let supported_groups = 196 + [ `X25519 ; `P384 ; `P256 ; `P521 ; 197 + `FFDHE2048 ; `FFDHE3072 ; `FFDHE4096 ; `FFDHE6144 ; `FFDHE8192 ] 198 + 199 + let elliptic_curve = function 200 + | `X25519 | `P256 | `P384 | `P521 -> true 201 + | `FFDHE2048 | `FFDHE3072 | `FFDHE4096 | `FFDHE6144 | `FFDHE8192 -> false 202 + 203 + let default_config = { 204 + ciphers = Ciphers.default ; 205 + protocol_versions = (`TLS_1_2, `TLS_1_3) ; 206 + signature_algorithms = default_signature_algorithms ; 207 + use_reneg = false ; 208 + authenticator = None ; 209 + peer_name = None ; 210 + own_certificates = `None ; 211 + acceptable_cas = [] ; 212 + session_cache = (fun _ -> None) ; 213 + cached_session = None ; 214 + cached_ticket = None ; 215 + alpn_protocols = [] ; 216 + groups = supported_groups ; 217 + ticket_cache = None ; 218 + zero_rtt = 0l ; 219 + ip = None ; 220 + } 221 + 222 + (* There are inter-configuration option constraints that are checked and 223 + adjusted here. The overall approach is if the client explicitly provided 224 + values, these are taken as granted (a conflict will result in an error). If 225 + the defaults are used, they are adjusted depending on the others. 226 + 227 + The options in question are: 228 + - ciphers, which before 1.3 include the key exchange (FFDHE, ECDHE, RSA) 229 + - groups, which name the FFDHE and ECDHE groups used for DH 230 + - signature_algorithms, which (since 1.2) specify the key type and algorithm 231 + used for signatures (RSA-PKCS, RSA-PSS, ECDSA/EdDSA) 232 + - certificate chains, which influence ciphers (before 1.3) and 233 + signature_algorithms 234 + 235 + Using everywhere the default (but a custom certificate / or multiple) result 236 + in a working configuration (where, depending on the certificate key type, 237 + some signature_algorithms and ciphersuites are removed). The provided server 238 + certificate may remove ciphers & signature_algorithms, but will only result 239 + in failure if these will then be empty. 240 + 241 + An invalid configuration is for example: only FFDHE ciphersuites, but no 242 + FFDHE groups. Or only EC signature algorithms, but only ciphers where the 243 + key type is RSA. 244 + 245 + At session initiation time, the server implementation selects cipher, 246 + certificate, signature_algorithm, and group depending on its configuration 247 + and client request. 248 + *) 249 + 250 + let ciphers_and_groups ?ciphers ?groups default_ciphers = 251 + let tls13 = function #Ciphersuite.ciphersuite13 -> true | _ -> false in 252 + match ciphers, groups with 253 + | None, None -> Ok (default_ciphers, supported_groups) 254 + | Some cs, None -> 255 + Ok (cs, 256 + let has_kex x = function 257 + | #Ciphersuite.ciphersuite13 -> true 258 + | c -> x = Ciphersuite.ciphersuite_kex c 259 + in 260 + begin 261 + match List.exists (has_kex `ECDHE) cs, List.exists (has_kex `FFDHE) cs with 262 + | true, true -> supported_groups 263 + | true, false -> 264 + Log.warn (fun m -> m "removed FFDHE groups (no FFDHE ciphersuite) from configuation"); 265 + List.filter elliptic_curve supported_groups 266 + | false, true -> 267 + Log.warn (fun m -> m "removed ECDHE groups (no ECDHE ciphersuite) from configuration"); 268 + List.filter (fun g -> not (elliptic_curve g)) supported_groups 269 + | false, false -> [] 270 + end) 271 + | None, Some g -> 272 + Ok (begin match List.partition elliptic_curve g with 273 + | [], [] -> 274 + Log.warn (fun m -> m "removed DHE and ECDHE ciphersuites (empty groups provided) from configuration"); 275 + List.filter (fun c -> not (Ciphersuite.ciphersuite_fs c)) default_ciphers 276 + | _::_, [] -> 277 + Log.warn (fun m -> m "removed DHE ciphersuites (no FFDHE groups provided) from configuration"); 278 + List.filter (fun c -> not (Ciphersuite.dhe_only c)) default_ciphers 279 + | [], _ :: _ -> 280 + Log.warn (fun m -> m "removed ECDHE ciphersuites (no EC groups provided) from configuration"); 281 + List.filter (fun c -> not (Ciphersuite.ecdhe_only c)) default_ciphers 282 + | _ -> default_ciphers 283 + end, g) 284 + | Some cs, Some g -> 285 + if List.exists Ciphersuite.ecdhe_only cs && not (List.exists elliptic_curve g) then 286 + Error (`Msg "ciphersuite with ECDHE provided, but no EC group") 287 + else if List.exists Ciphersuite.dhe_only cs && not (List.exists (fun g -> not (elliptic_curve g)) g) then 288 + Error (`Msg "ciphersuite with FFDHE provided, but no FF group") 289 + else if List.exists Ciphersuite.ciphersuite_fs cs && g = [] then 290 + Error (`Msg "ciphersuite with forward security provided, but no group") 291 + else if List.exists elliptic_curve g && not (List.exists Ciphersuite.ecdhe cs) then 292 + Error (`Msg "EC group provided, but no ciphersuite with ECDHE") 293 + else if List.exists (fun g -> not (elliptic_curve g)) g && 294 + not (List.exists (fun c -> Ciphersuite.dhe_only c || tls13 c) cs) 295 + then 296 + Error (`Msg "FF group provided, but no ciphersuite with DHE") 297 + else 298 + Ok (cs, g) 299 + 300 + let ciphers_and_sig_alg ?ciphers ?signature_algorithms default_ciphers = 301 + let tls13 = function #Ciphersuite.ciphersuite13 -> true | _ -> false in 302 + let default_sa_from_ciphers c = 303 + let has_key k c = tls13 c || k = Ciphersuite.ciphersuite_keytype c in 304 + match List.exists (has_key `RSA) c, List.exists (has_key `EC) c with 305 + | true, true -> Ok supported_signature_algorithms 306 + | true, false -> 307 + Log.warn (fun m -> m "removed EC signature algorithms (no EC ciphersuite present)"); 308 + Ok (List.filter rsa_sigalg supported_signature_algorithms) 309 + | false, true -> 310 + Log.warn (fun m -> m "removed RSA signature algorithms (no RSA ciphersuite present)"); 311 + Ok (List.filter (fun sa -> not (rsa_sigalg sa)) supported_signature_algorithms) 312 + | false, false -> 313 + Error (`Msg "ciphersuite list without RSA and EC keys") 314 + in 315 + let ( let* ) = Result.bind in 316 + match ciphers, signature_algorithms with 317 + | None, None -> 318 + let* sig_algs = default_sa_from_ciphers default_ciphers in 319 + Ok (default_ciphers, sig_algs) 320 + | Some c, None -> 321 + let* sig_algs = default_sa_from_ciphers c in 322 + Ok (c, sig_algs) 323 + | None, Some sa -> 324 + begin match List.partition rsa_sigalg sa with 325 + | [], [] -> Error (`Msg "empty signature algorithms provided") 326 + | _::_, [] -> 327 + Log.warn (fun m -> m "removing EC ciphers (no EC signature algorithm provided)"); 328 + Ok (List.filter 329 + (fun c -> tls13 c || not (Ciphersuite.ciphersuite_keytype c = `EC)) 330 + default_ciphers, 331 + sa) 332 + | [], _::_ -> 333 + Log.warn (fun m -> m "removing RSA ciphers (no RSA signature algorithm provided)"); 334 + Ok (List.filter 335 + (fun c -> tls13 c || not (Ciphersuite.ciphersuite_keytype c = `RSA)) 336 + default_ciphers, 337 + sa) 338 + | _::_, _::_ -> Ok (default_ciphers, sa) 339 + end 340 + | Some c, Some sa -> 341 + if List.exists rsa_sigalg sa && not (List.exists (fun c -> Ciphersuite.ciphersuite_keytype c = `RSA) c) then 342 + Error (`Msg "RSA signature algorithm, but no ciphersuites with RSA keys") 343 + else if List.exists (fun s -> not (rsa_sigalg s)) sa && not (List.exists (fun c -> Ciphersuite.ciphersuite_keytype c = `EC) c) then 344 + Error (`Msg "EC signature algorithm, but no ciphersuites with EC keys") 345 + else if List.exists (fun c -> Ciphersuite.ciphersuite_keytype c = `RSA) c && not (List.exists rsa_sigalg sa) then 346 + Error (`Msg "RSA ciphersuite, but no RSA signature algorithm") 347 + else if List.exists (fun c -> Ciphersuite.ciphersuite_keytype c = `EC) c && not (List.exists (fun s -> not (rsa_sigalg s)) sa) then 348 + Error (`Msg "EC ciphersuite, but no EC signature algorithm") 349 + else 350 + Ok (c, sa) 351 + 352 + let validate_common config = 353 + let ( let* ) = Result.bind in 354 + let (v_min, v_max) = config.protocol_versions in 355 + if v_max < v_min then 356 + Error (`Msg "bad version range") 357 + else 358 + let* ciphers, signature_algorithms = 359 + match v_min, v_max with 360 + | _, `TLS_1_1 | _, `TLS_1_0 -> 361 + Log.warn (fun m -> m "TLS 1.0 or TLS 1.1 as maximum version configured, removing 1.2 and 1.3 ciphersuites"); 362 + Ok (List.filter (fun c -> 363 + not (Ciphersuite.ciphersuite_tls12_only c || Ciphersuite.ciphersuite_tls13 c)) 364 + config.ciphers, 365 + []) 366 + | _, `TLS_1_2 -> 367 + if config.signature_algorithms = [] then 368 + Error (`Msg "TLS 1.2 configured but no signature algorithms provided") 369 + else begin 370 + Log.warn (fun m -> m "TLS 1.2 as maximum version configured, removing 1.3 cipher suites"); 371 + Ok (List.filter 372 + (fun c -> not (Ciphersuite.ciphersuite_tls13 c)) config.ciphers, 373 + config.signature_algorithms) 374 + end 375 + | `TLS_1_3, `TLS_1_3 -> 376 + let sa = List.filter tls13_sigalg config.signature_algorithms in 377 + if sa = [] then 378 + Error (`Msg "TLS 1.3 configured but no 1.3 signature algorithms provided") 379 + else begin 380 + Log.warn (fun m -> m "only TLS 1.3 configured, removing pre-1.3 cipher suites and signature algorithms"); 381 + Ok (List.filter Ciphersuite.ciphersuite_tls13 config.ciphers, sa) 382 + end 383 + | _ -> Ok (config.ciphers, config.signature_algorithms) 384 + in 385 + if not (Utils.List_set.is_proper_set ciphers) then 386 + Error (`Msg "set of ciphers is not a proper set") 387 + else if List.length ciphers = 0 then 388 + Error (`Msg "set of ciphers is empty") 389 + else if not (Utils.List_set.is_proper_set config.groups) then 390 + Error (`Msg "set of groups is not a proper set") 391 + else if not (Utils.List_set.is_proper_set signature_algorithms) then 392 + Error (`Msg "set of signature algorithms is not a proper set") 393 + else if List.exists (fun proto -> let len = String.length proto in len = 0 || len > 255) config.alpn_protocols then 394 + Error (`Msg "invalid alpn protocol") 395 + else if List.length config.alpn_protocols > 0xffff then 396 + Error (`Msg "alpn protocols list too large") 397 + else 398 + Ok { config with ciphers ; signature_algorithms } 399 + 400 + let validate_certificate_chain = function 401 + | (s::chain, priv) -> 402 + let ( let* ) = Result.bind in 403 + let pub = X509.Private_key.public priv in 404 + let* () = 405 + match pub with 406 + | `RSA pub when Mirage_crypto_pk.Rsa.pub_bits pub < min_rsa_key_size -> 407 + Error (`Msg "RSA key too short!") 408 + | _ -> Ok () 409 + in 410 + let* () = 411 + let eq_pub a b = 412 + String.equal (X509.Public_key.fingerprint a) (X509.Public_key.fingerprint b) 413 + in 414 + if not (eq_pub pub (X509.Certificate.public_key s)) then 415 + Error (`Msg "public / private key combination" ) 416 + else 417 + Ok () 418 + in 419 + ( match Utils.init_and_last chain with 420 + | Some (ch, trust) -> 421 + (* TODO: verify that certificates are x509 v3 if TLS_1_2 *) 422 + ( match X509.Validation.verify_chain_of_trust ~time:(fun () -> None) ~host:None ~anchors:[trust] (s :: ch) with 423 + | Ok _ -> Ok () 424 + | Error x -> 425 + let s = Fmt.to_to_string X509.Validation.pp_validation_error x in 426 + Error (`Msg ("certificate chain does not validate: " ^ s))) 427 + | None -> Ok () ) 428 + | _ -> Error (`Msg "certificate chain") 429 + 430 + let validate_client config = 431 + match config.own_certificates with 432 + | `None -> Ok () 433 + | `Single c -> validate_certificate_chain c 434 + | _ -> Error (`Msg "multiple client certificates not supported in client config") 435 + 436 + let non_overlapping cs = 437 + let namessets = 438 + List.filter_map (function 439 + | (s :: _, _) -> Some s 440 + | _ -> None) 441 + cs 442 + |> List.map X509.Certificate.hostnames 443 + in 444 + let rec check = function 445 + | [] -> () 446 + | s::ss -> 447 + if not (List.for_all (fun ss' -> 448 + X509.Host.Set.is_empty (X509.Host.Set.inter s ss')) 449 + ss) 450 + then 451 + invalid_arg "overlapping names in certificates" 452 + else 453 + check ss 454 + in 455 + check namessets 456 + 457 + module KU = Set.Make (struct 458 + type t = X509.Extension.key_usage 459 + let compare a b = compare a b 460 + end) 461 + 462 + module PK = Map.Make (struct 463 + type t = [ `RSA | `ED25519 | `P256 | `P384 | `P521 ] 464 + let compare a b = compare a b 465 + end) 466 + 467 + let validate_server config = 468 + let ( let* ) = Result.bind in 469 + let open Ciphersuite in 470 + let usages = 471 + List.fold_left 472 + (fun acc c -> KU.add (required_usage (ciphersuite_kex c)) acc) 473 + KU.empty config.ciphers 474 + in 475 + let* certificate_chains = 476 + match config.own_certificates with 477 + | `Single c -> Ok [c] 478 + | `Multiple cs -> Ok cs 479 + | `Multiple_default (c, cs) -> Ok (c :: cs) 480 + | `None -> Error (`Msg "no server certificate provided") 481 + in 482 + let* server_certs = 483 + List.fold_left (fun acc cc -> 484 + let* acc = acc in 485 + match cc with 486 + | (s::_,_) -> Ok (s :: acc) 487 + | _ -> Error (`Msg "empty certificate chain")) 488 + (Ok []) certificate_chains 489 + in 490 + let* () = 491 + if not 492 + (KU.for_all (fun u -> 493 + List.exists (supports_key_usage ~not_present:true u) server_certs) 494 + usages) 495 + then 496 + Error (`Msg "certificate usage does not match") 497 + else 498 + Ok () 499 + in 500 + let* () = 501 + List.fold_left (fun acc cc -> 502 + let* () = acc in 503 + validate_certificate_chain cc) 504 + (Ok ()) certificate_chains 505 + in 506 + let rsa_cert, ec_cert = 507 + let is_ec_cert c = match X509.Certificate.public_key c with 508 + | `ED25519 _ | `P256 _ | `P384 _ | `P521 _ -> true 509 + | _ -> false 510 + and is_rsa_cert c = match X509.Certificate.public_key c with 511 + | `RSA _ -> true | _ -> false 512 + in 513 + List.exists is_rsa_cert server_certs, 514 + List.exists is_ec_cert server_certs 515 + in 516 + let ciphers = 517 + List.filter 518 + (function 519 + | #Ciphersuite.ciphersuite13 -> true 520 + | c -> 521 + let keytype = ciphersuite_keytype c in 522 + (rsa_cert && keytype = `RSA) || (ec_cert && keytype = `EC)) 523 + config.ciphers 524 + in 525 + ( match config.own_certificates with 526 + | `Multiple cs 527 + | `Multiple_default (_, cs) -> 528 + let add k v acc = match PK.find_opt k acc with 529 + | None -> PK.add k [v] acc 530 + | Some r -> PK.add k (v :: r) acc 531 + in 532 + let pk = 533 + List.fold_left (fun acc cs -> 534 + match snd cs with 535 + | `RSA _ -> add `RSA cs acc 536 + | `ED25519 _ -> add `ED25519 cs acc 537 + | `P256 _ -> add `P256 cs acc 538 + | `P384 _ -> add `P384 cs acc 539 + | `P521 _ -> add `P521 cs acc) 540 + PK.empty cs 541 + in 542 + PK.iter (fun _ chains -> non_overlapping chains) pk 543 + | _ -> () ); 544 + Ok { config with ciphers } 545 + 546 + let validate_keys_sig_algs config = 547 + let ( let* ) = Result.bind in 548 + let _, v_max = config.protocol_versions in 549 + if v_max = `TLS_1_2 || v_max = `TLS_1_3 then 550 + let* certificate_chains = 551 + match config.own_certificates with 552 + | `Single c -> Ok [c] 553 + | `Multiple cs -> Ok cs 554 + | `Multiple_default (c, cs) -> Ok (c :: cs) 555 + | `None -> Error (`Msg "no server certificate provided") 556 + in 557 + let* server_keys = 558 + List.fold_left (fun acc cc -> 559 + let* acc = acc in 560 + match cc with 561 + | (s::_,_) -> Ok (X509.Certificate.public_key s :: acc) 562 + | _ -> Error (`Msg "empty certificate chain")) 563 + (Ok []) certificate_chains 564 + in 565 + if not 566 + (List.for_all (fun cert -> 567 + List.exists (pk_matches_sa cert) config.signature_algorithms) 568 + server_keys) 569 + then 570 + Error (`Msg "certificate provided which does not allow any signature algorithm") 571 + else 572 + Ok () 573 + else 574 + Ok () 575 + 576 + type client = config 577 + type server = config 578 + 579 + let of_server conf = conf 580 + and of_client conf = conf 581 + 582 + let peer conf name = { conf with peer_name = Some name } 583 + 584 + let with_authenticator conf auth = { conf with authenticator = Some auth } 585 + 586 + let with_own_certificates conf own_certificates = { conf with own_certificates } 587 + 588 + let with_acceptable_cas conf acceptable_cas = { conf with acceptable_cas } 589 + 590 + let (<?>) ma b = match ma with None -> b | Some a -> a 591 + 592 + let client 593 + ~authenticator ?peer_name ?ciphers ?version ?signature_algorithms ?reneg ?certificates ?cached_session ?cached_ticket ?ticket_cache ?alpn_protocols ?groups ?ip () = 594 + let ( let* ) = Result.bind in 595 + let* ciphers', groups = ciphers_and_groups ?ciphers ?groups default_config.ciphers in 596 + let* ciphers, signature_algorithms = ciphers_and_sig_alg ?ciphers ?signature_algorithms ciphers' in 597 + let config = 598 + { default_config with 599 + authenticator = Some authenticator ; 600 + ciphers ; 601 + protocol_versions = version <?> default_config.protocol_versions ; 602 + signature_algorithms ; 603 + use_reneg = reneg <?> default_config.use_reneg ; 604 + own_certificates = certificates <?> default_config.own_certificates ; 605 + peer_name = peer_name ; 606 + cached_session = cached_session ; 607 + alpn_protocols = alpn_protocols <?> default_config.alpn_protocols ; 608 + ticket_cache = ticket_cache ; 609 + cached_ticket = cached_ticket ; 610 + groups ; 611 + ip ; 612 + } in 613 + let* config = validate_common config in 614 + let* () = validate_client config in 615 + Log.debug (fun m -> m "client with %a" pp_config config); 616 + Ok config 617 + 618 + let server 619 + ?ciphers ?version ?signature_algorithms ?reneg ?certificates ?acceptable_cas ?authenticator ?session_cache ?ticket_cache ?alpn_protocols ?groups ?zero_rtt ?ip () = 620 + let ( let* ) = Result.bind in 621 + let* ciphers', groups = ciphers_and_groups ?ciphers ?groups default_config.ciphers in 622 + let* ciphers, signature_algorithms = ciphers_and_sig_alg ?ciphers ?signature_algorithms ciphers' in 623 + let config = 624 + { default_config with 625 + ciphers ; 626 + protocol_versions = version <?> default_config.protocol_versions ; 627 + signature_algorithms ; 628 + use_reneg = reneg <?> default_config.use_reneg ; 629 + own_certificates = certificates <?> default_config.own_certificates ; 630 + acceptable_cas = acceptable_cas <?> default_config.acceptable_cas ; 631 + authenticator = authenticator ; 632 + session_cache = session_cache <?> default_config.session_cache ; 633 + alpn_protocols = alpn_protocols <?> default_config.alpn_protocols ; 634 + ticket_cache = ticket_cache ; 635 + groups ; 636 + zero_rtt = zero_rtt <?> default_config.zero_rtt ; 637 + ip ; 638 + } in 639 + let* config = validate_server config in 640 + let* config = validate_common config in 641 + let* () = validate_keys_sig_algs config in 642 + Log.debug (fun m -> m "server with %a" pp_config config); 643 + Ok config
+174
vendor/opam/tls/lib/config.mli
··· 1 + open Core 2 + 3 + (** Configuration of the TLS stack *) 4 + 5 + (** {1 Config type} *) 6 + 7 + (** certificate chain and private key of the first certificate *) 8 + type certchain = X509.Certificate.t list * X509.Private_key.t 9 + 10 + (** polymorphic variant of own certificates *) 11 + type own_cert = [ 12 + | `None 13 + | `Single of certchain 14 + | `Multiple of certchain list 15 + | `Multiple_default of certchain * certchain list 16 + ] 17 + 18 + type session_cache = SessionID.t -> epoch_data option 19 + 20 + type ticket_cache = { 21 + lookup : string -> (psk13 * epoch_data) option ; 22 + ticket_granted : psk13 -> epoch_data -> unit ; 23 + lifetime : int32 ; 24 + timestamp : unit -> Ptime.t 25 + } 26 + 27 + (** configuration parameters *) 28 + type config = private { 29 + ciphers : Ciphersuite.ciphersuite list ; (** ordered list (regarding preference) of supported cipher suites *) 30 + protocol_versions : tls_version * tls_version ; (** supported protocol versions (min, max) *) 31 + signature_algorithms : signature_algorithm list ; (** ordered list of supported signature algorithms (regarding preference) *) 32 + use_reneg : bool ; (** endpoint should accept renegotiation requests *) 33 + authenticator : X509.Authenticator.t option ; (** optional X509 authenticator *) 34 + peer_name : [ `host ] Domain_name.t option ; (** optional name of other endpoint (used for SNI RFC4366) *) 35 + own_certificates : own_cert ; (** optional default certificate chain and other certificate chains *) 36 + acceptable_cas : X509.Distinguished_name.t list ; (** ordered list of acceptable certificate authorities *) 37 + session_cache : session_cache ; 38 + ticket_cache : ticket_cache option ; 39 + cached_session : epoch_data option ; 40 + cached_ticket : (psk13 * epoch_data) option ; 41 + alpn_protocols : string list ; (** optional ordered list of accepted alpn_protocols *) 42 + groups : group list ; (** the first FFDHE will be used for TLS 1.2 and below if a DHE ciphersuite is used *) 43 + zero_rtt : int32 ; 44 + ip : Ipaddr.t option ; 45 + } 46 + 47 + (** [ciphers13 config] are the ciphersuites for TLS 1.3 in the configuration. *) 48 + val ciphers13 : config -> Ciphersuite.ciphersuite13 list 49 + 50 + (** opaque type of a client configuration *) 51 + type client 52 + 53 + (** opaque type of a server configuration *) 54 + type server 55 + 56 + (** {1 Constructors} *) 57 + 58 + (** [client authenticator ?peer_name ?ciphers ?version ?hashes ?reneg ?certificates ?alpn_protocols] is 59 + [client] configuration with the given parameters. Returns an error if the configuration is invalid. *) 60 + val client : 61 + authenticator : X509.Authenticator.t -> 62 + ?peer_name : [ `host ] Domain_name.t -> 63 + ?ciphers : Ciphersuite.ciphersuite list -> 64 + ?version : tls_version * tls_version -> 65 + ?signature_algorithms : signature_algorithm list -> 66 + ?reneg : bool -> 67 + ?certificates : own_cert -> 68 + ?cached_session : epoch_data -> 69 + ?cached_ticket : psk13 * epoch_data -> 70 + ?ticket_cache : ticket_cache -> 71 + ?alpn_protocols : string list -> 72 + ?groups : group list -> 73 + ?ip : Ipaddr.t -> 74 + unit -> (client, [> `Msg of string ]) result 75 + 76 + (** [server ?ciphers ?version ?hashes ?reneg ?certificates ?acceptable_cas ?authenticator ?alpn_protocols] 77 + is [server] configuration with the given parameters. Returns an error if the configuration is invalid. *) 78 + val server : 79 + ?ciphers : Ciphersuite.ciphersuite list -> 80 + ?version : tls_version * tls_version -> 81 + ?signature_algorithms : signature_algorithm list -> 82 + ?reneg : bool -> 83 + ?certificates : own_cert -> 84 + ?acceptable_cas : X509.Distinguished_name.t list -> 85 + ?authenticator : X509.Authenticator.t -> 86 + ?session_cache : session_cache -> 87 + ?ticket_cache : ticket_cache -> 88 + ?alpn_protocols : string list -> 89 + ?groups : group list -> 90 + ?zero_rtt : int32 -> 91 + ?ip : Ipaddr.t -> 92 + unit -> (server, [> `Msg of string ]) result 93 + 94 + (** [peer client name] is [client] with [name] as [peer_name] *) 95 + val peer : client -> [ `host ] Domain_name.t -> client 96 + 97 + (** {1 Note on ALPN protocol selection} 98 + 99 + Both {!val:client} and {!val:server} constructors accept an [alpn_protocols] list. The list for server 100 + should be given in a descending order of preference. In the case of protocol selection, the server will 101 + iterate its list and select the first element that the client's list also advertises. 102 + 103 + For example, if the client advertises [["foo"; "bar"; "baz"]] and the server has [["bar"; "foo"]], 104 + ["bar"] will be selected as the protocol of the handshake. *) 105 + 106 + (** {1 Utility functions} *) 107 + 108 + (** [default_signature_algorithms] is a list of signature algorithms used by default *) 109 + val default_signature_algorithms : signature_algorithm list 110 + 111 + (** [supported_signature_algorithms] is a list of supported signature algorithms by this library *) 112 + val supported_signature_algorithms : signature_algorithm list 113 + 114 + (** [min_dh_size] is minimal diffie hellman group size in bits (currently 1024) *) 115 + val min_dh_size : int 116 + 117 + (** [supported_groups] are the Diffie-Hellman groups supported in this 118 + library. *) 119 + val supported_groups : group list 120 + 121 + (** [elliptic_curve group] is [true] if group is an elliptic curve, [false] 122 + otherwise. *) 123 + val elliptic_curve : group -> bool 124 + 125 + (** [min_rsa_key_size] is minimal RSA modulus key size in bits (currently 1024) *) 126 + val min_rsa_key_size : int 127 + 128 + (** Cipher selection *) 129 + module Ciphers : sig 130 + 131 + open Ciphersuite 132 + 133 + (** Cipher selection related utilities. *) 134 + 135 + (** {1 Cipher selection} *) 136 + 137 + val default : ciphersuite list 138 + (** [default] is a list of ciphersuites this library uses by default. *) 139 + 140 + val supported : ciphersuite list 141 + (** [supported] is a list of ciphersuites this library supports 142 + (larger than [default]). *) 143 + 144 + val fs : ciphersuite list 145 + (** [fs] is a list of ciphersuites which provide forward secrecy 146 + (sublist of [default]). *) 147 + 148 + val http2 : ciphersuite list 149 + (** [http2] is a list of ciphersuites which are allowed to be used with HTTP2: 150 + not a member of 151 + {{:https://httpwg.org/specs/rfc7540.html#BadCipherSuites}bad cipher 152 + suites}. These are only ephemeral key exchanges with AEAD ciphers. *) 153 + 154 + val fs_of : ciphersuite list -> ciphersuite list 155 + (** [fs_of ciphers] selects all ciphersuites which provide forward 156 + secrecy from [ciphers]. *) 157 + end 158 + 159 + (** {1 Internal use only} *) 160 + 161 + (** [of_client client] is a client configuration for [client] *) 162 + val of_client : client -> config 163 + 164 + (** [of_server server] is a server configuration for [server] *) 165 + val of_server : server -> config 166 + 167 + (** [with_authenticator config auth] is [config] with [auth] as [authenticator] *) 168 + val with_authenticator : config -> X509.Authenticator.t -> config 169 + 170 + (** [with_own_certificates config cert] is [config] with [cert] as [own_cert] *) 171 + val with_own_certificates : config -> own_cert -> config 172 + 173 + (** [with_acceptable_cas config cas] is [config] with [cas] as [accepted_cas] *) 174 + val with_acceptable_cas : config -> X509.Distinguished_name.t list -> config
+501
vendor/opam/tls/lib/core.ml
··· 1 + (** Core type definitions *) 2 + 3 + open Packet 4 + open Ciphersuite 5 + 6 + let ( let* ) = Result.bind 7 + 8 + let guard p e = if p then Ok () else Error e 9 + 10 + let split_str ?(start = 0) str off = 11 + String.sub str start off, 12 + String.sub str (start + off) (String.length str - off - start) 13 + 14 + let map_reader_error r = 15 + Result.map_error (fun e -> `Fatal e) r 16 + 17 + type tls13 = [ `TLS_1_3 ] 18 + 19 + let pp_tls13 ppf `TLS_1_3 = Fmt.string ppf "TLS 1.3" 20 + 21 + type tls_before_13 = [ 22 + | `TLS_1_0 23 + | `TLS_1_1 24 + | `TLS_1_2 25 + ] 26 + 27 + let pp_tls_before_13 ppf = function 28 + | `TLS_1_0 -> Fmt.string ppf "TLS 1.0" 29 + | `TLS_1_1 -> Fmt.string ppf "TLS 1.1" 30 + | `TLS_1_2 -> Fmt.string ppf "TLS 1.2" 31 + 32 + type tls_version = [ tls13 | tls_before_13 ] 33 + 34 + let pp_tls_version ppf = function 35 + | #tls13 as v -> pp_tls13 ppf v 36 + | #tls_before_13 as v -> pp_tls_before_13 ppf v 37 + 38 + let pair_of_tls_version = function 39 + | `TLS_1_0 -> (3, 1) 40 + | `TLS_1_1 -> (3, 2) 41 + | `TLS_1_2 -> (3, 3) 42 + | `TLS_1_3 -> (3, 4) 43 + 44 + let compare_tls_version a b = match a, b with 45 + | `TLS_1_0, `TLS_1_0 -> 0 | `TLS_1_0, _ -> -1 | _, `TLS_1_0 -> 1 46 + | `TLS_1_1, `TLS_1_1 -> 0 | `TLS_1_1, _ -> -1 | _, `TLS_1_1 -> 1 47 + | `TLS_1_2, `TLS_1_2 -> 0 | `TLS_1_2, _ -> -1 | _, `TLS_1_2 -> 1 48 + | `TLS_1_3, `TLS_1_3 -> 0 49 + 50 + let next = function 51 + | `TLS_1_0 -> Some `TLS_1_1 52 + | `TLS_1_1 -> Some `TLS_1_2 53 + | `TLS_1_2 -> Some `TLS_1_3 54 + | `TLS_1_3 -> None 55 + 56 + let all_versions (min, max) = 57 + let rec gen curr = 58 + if compare_tls_version max curr >= 0 then 59 + match next curr with 60 + | None -> [curr] 61 + | Some c -> curr :: gen c 62 + else 63 + [] 64 + in 65 + List.rev (gen min) 66 + 67 + let tls_version_of_pair = function 68 + | (3, 1) -> Some `TLS_1_0 69 + | (3, 2) -> Some `TLS_1_1 70 + | (3, 3) -> Some `TLS_1_2 71 + | (3, 4) -> Some `TLS_1_3 72 + | _ -> None 73 + 74 + type tls_any_version = [ 75 + | tls_version 76 + | `SSL_3 77 + | `TLS_1_X of int 78 + ] 79 + 80 + let pp_tls_any_version ppf = function 81 + | #tls_version as v -> pp_tls_version ppf v 82 + | `SSL_3 -> Fmt.string ppf "SSL3" 83 + | `TLS_1_X x -> Fmt.pf ppf "TLS1.%u" x 84 + 85 + let any_version_to_version = function 86 + | #tls_version as v -> Some v 87 + | _ -> None 88 + 89 + let version_eq a b = 90 + match a with 91 + | #tls_version as x -> compare_tls_version x b = 0 92 + | _ -> false 93 + 94 + let version_ge a b = 95 + match a with 96 + | #tls_version as x -> compare_tls_version x b >= 0 97 + | `SSL_3 -> false 98 + | `TLS_1_X _ -> true 99 + 100 + let tls_any_version_of_pair x = 101 + match tls_version_of_pair x with 102 + | Some v -> Some v 103 + | None -> 104 + match x with 105 + | (3, 0) -> Some `SSL_3 106 + | (3, x) -> Some (`TLS_1_X x) 107 + | _ -> None 108 + 109 + let pair_of_tls_any_version = function 110 + | #tls_version as x -> pair_of_tls_version x 111 + | `SSL_3 -> (3, 0) 112 + | `TLS_1_X m -> (3, m) 113 + 114 + let max_protocol_version (_, hi) = hi 115 + let min_protocol_version (lo, _) = lo 116 + 117 + type tls_hdr = { 118 + content_type : content_type; 119 + version : tls_any_version; 120 + } 121 + 122 + let pp_tls_hdr ppf { content_type ; version } = 123 + Fmt.pf ppf "content type: %a version: %a" pp_content_type content_type 124 + pp_tls_any_version version 125 + 126 + module SessionID = struct 127 + type t = string 128 + let compare = String.compare 129 + let hash t = Hashtbl.hash t 130 + let equal = String.equal 131 + end 132 + 133 + module PreSharedKeyID = struct 134 + type t = string 135 + let compare = String.compare 136 + let hash t = Hashtbl.hash t 137 + let equal = String.equal 138 + end 139 + 140 + type psk_identity = (string * int32) * string 141 + 142 + let binders_len psks = 143 + let binder_len (_, binder) = 144 + String.length binder + 1 (* binder len *) 145 + in 146 + 2 (* binder len *) + List.fold_left (+) 0 (List.map binder_len psks) 147 + 148 + type group = [ 149 + | `FFDHE2048 150 + | `FFDHE3072 151 + | `FFDHE4096 152 + | `FFDHE6144 153 + | `FFDHE8192 154 + | `X25519 155 + | `P256 156 + | `P384 157 + | `P521 158 + ] 159 + 160 + let pp_group ppf = function 161 + | `FFDHE2048 -> Fmt.string ppf "FFDHE2048" 162 + | `FFDHE3072 -> Fmt.string ppf "FFDHE3072" 163 + | `FFDHE4096 -> Fmt.string ppf "FFDHE4096" 164 + | `FFDHE6144 -> Fmt.string ppf "FFDHE6144" 165 + | `FFDHE8192 -> Fmt.string ppf "FFDHE8192" 166 + | `X25519 -> Fmt.string ppf "X25519" 167 + | `P256 -> Fmt.string ppf "P256" 168 + | `P384 -> Fmt.string ppf "P384" 169 + | `P521 -> Fmt.string ppf "P521" 170 + 171 + let named_group_to_group = function 172 + | FFDHE2048 -> Some `FFDHE2048 173 + | FFDHE3072 -> Some `FFDHE3072 174 + | FFDHE4096 -> Some `FFDHE4096 175 + | FFDHE6144 -> Some `FFDHE6144 176 + | FFDHE8192 -> Some `FFDHE8192 177 + | X25519 -> Some `X25519 178 + | SECP256R1 -> Some `P256 179 + | SECP384R1 -> Some `P384 180 + | SECP521R1 -> Some `P521 181 + | _ -> None 182 + 183 + let group_to_named_group = function 184 + | `FFDHE2048 -> FFDHE2048 185 + | `FFDHE3072 -> FFDHE3072 186 + | `FFDHE4096 -> FFDHE4096 187 + | `FFDHE6144 -> FFDHE6144 188 + | `FFDHE8192 -> FFDHE8192 189 + | `X25519 -> X25519 190 + | `P256 -> SECP256R1 191 + | `P384 -> SECP384R1 192 + | `P521 -> SECP521R1 193 + 194 + let group_to_impl = function 195 + | `FFDHE2048 -> `Finite_field Mirage_crypto_pk.Dh.Group.ffdhe2048 196 + | `FFDHE3072 -> `Finite_field Mirage_crypto_pk.Dh.Group.ffdhe3072 197 + | `FFDHE4096 -> `Finite_field Mirage_crypto_pk.Dh.Group.ffdhe4096 198 + | `FFDHE6144 -> `Finite_field Mirage_crypto_pk.Dh.Group.ffdhe6144 199 + | `FFDHE8192 -> `Finite_field Mirage_crypto_pk.Dh.Group.ffdhe8192 200 + | `X25519 -> `X25519 201 + | `P256 -> `P256 202 + | `P384 -> `P384 203 + | `P521 -> `P521 204 + 205 + type signature_algorithm = [ 206 + | `RSA_PKCS1_MD5 207 + | `RSA_PKCS1_SHA1 208 + | `RSA_PKCS1_SHA224 209 + | `RSA_PKCS1_SHA256 210 + | `RSA_PKCS1_SHA384 211 + | `RSA_PKCS1_SHA512 212 + | `ECDSA_SECP256R1_SHA1 213 + | `ECDSA_SECP256R1_SHA256 214 + | `ECDSA_SECP384R1_SHA384 215 + | `ECDSA_SECP521R1_SHA512 216 + | `RSA_PSS_RSAENC_SHA256 217 + | `RSA_PSS_RSAENC_SHA384 218 + | `RSA_PSS_RSAENC_SHA512 219 + | `ED25519 220 + (* | `ED448 221 + | `RSA_PSS_PSS_SHA256 222 + | `RSA_PSS_PSS_SHA384 223 + | `RSA_PSS_PSS_SHA512 *) 224 + ] 225 + 226 + let hash_of_signature_algorithm = function 227 + | `RSA_PKCS1_MD5 -> `MD5 228 + | `RSA_PKCS1_SHA1 -> `SHA1 229 + | `RSA_PKCS1_SHA224 -> `SHA224 230 + | `RSA_PKCS1_SHA256 -> `SHA256 231 + | `RSA_PKCS1_SHA384 -> `SHA384 232 + | `RSA_PKCS1_SHA512 -> `SHA512 233 + | `RSA_PSS_RSAENC_SHA256 -> `SHA256 234 + | `RSA_PSS_RSAENC_SHA384 -> `SHA384 235 + | `RSA_PSS_RSAENC_SHA512 -> `SHA512 236 + | `ECDSA_SECP256R1_SHA1 -> `SHA1 237 + | `ECDSA_SECP256R1_SHA256 -> `SHA256 238 + | `ECDSA_SECP384R1_SHA384 -> `SHA384 239 + | `ECDSA_SECP521R1_SHA512 -> `SHA512 240 + | `ED25519 -> `SHA512 241 + 242 + let signature_scheme_of_signature_algorithm = function 243 + | `RSA_PKCS1_MD5 -> `RSA_PKCS1 244 + | `RSA_PKCS1_SHA1 -> `RSA_PKCS1 245 + | `RSA_PKCS1_SHA224 -> `RSA_PKCS1 246 + | `RSA_PKCS1_SHA256 -> `RSA_PKCS1 247 + | `RSA_PKCS1_SHA384 -> `RSA_PKCS1 248 + | `RSA_PKCS1_SHA512 -> `RSA_PKCS1 249 + | `RSA_PSS_RSAENC_SHA256 -> `RSA_PSS 250 + | `RSA_PSS_RSAENC_SHA384 -> `RSA_PSS 251 + | `RSA_PSS_RSAENC_SHA512 -> `RSA_PSS 252 + | `ECDSA_SECP256R1_SHA1 -> `ECDSA 253 + | `ECDSA_SECP256R1_SHA256 -> `ECDSA 254 + | `ECDSA_SECP384R1_SHA384 -> `ECDSA 255 + | `ECDSA_SECP521R1_SHA512 -> `ECDSA 256 + | `ED25519 -> `ED25519 257 + 258 + let pp_signature_algorithm ppf sa = 259 + let h = hash_of_signature_algorithm sa 260 + and ss = signature_scheme_of_signature_algorithm sa 261 + in 262 + let pp_signature_scheme ppf = function 263 + | `RSA_PKCS1 -> Fmt.string ppf "RSA-PKCS1" 264 + | `RSA_PSS -> Fmt.string ppf "RSA-PSS" 265 + | `ECDSA -> Fmt.string ppf "ECDSA" 266 + | `ED25519 -> Fmt.string ppf "ED25519" 267 + in 268 + match ss with 269 + | `ED25519 -> Fmt.pf ppf "%a" pp_signature_scheme ss 270 + | `ECDSA -> 271 + let group_to_string = function 272 + | `ECDSA_SECP256R1_SHA1 -> "SECP256R1" 273 + | `ECDSA_SECP256R1_SHA256 -> "SECP256R1" 274 + | `ECDSA_SECP384R1_SHA384 -> "SECP384R1" 275 + | `ECDSA_SECP521R1_SHA512 -> "SECP521R1" 276 + | _ -> assert false 277 + in 278 + Fmt.pf ppf "%a %s %a" pp_signature_scheme ss (group_to_string sa) pp_hash h 279 + | _ -> Fmt.pf ppf "%a %a" pp_signature_scheme ss pp_hash h 280 + 281 + let rsa_sigalg = function 282 + | `RSA_PSS_RSAENC_SHA256 | `RSA_PSS_RSAENC_SHA384 | `RSA_PSS_RSAENC_SHA512 283 + | `RSA_PKCS1_SHA256 | `RSA_PKCS1_SHA384 | `RSA_PKCS1_SHA512 284 + | `RSA_PKCS1_SHA224 | `RSA_PKCS1_SHA1 | `RSA_PKCS1_MD5 -> true 285 + | `ECDSA_SECP256R1_SHA1 | `ECDSA_SECP256R1_SHA256 | `ECDSA_SECP384R1_SHA384 286 + | `ECDSA_SECP521R1_SHA512 | `ED25519 -> false 287 + 288 + let tls13_sigalg = function 289 + | `RSA_PSS_RSAENC_SHA256 | `RSA_PSS_RSAENC_SHA384 | `RSA_PSS_RSAENC_SHA512 290 + | `ECDSA_SECP256R1_SHA256 | `ECDSA_SECP384R1_SHA384 291 + | `ECDSA_SECP521R1_SHA512 | `ED25519 -> true 292 + | `RSA_PKCS1_SHA256 | `RSA_PKCS1_SHA384 | `RSA_PKCS1_SHA512 293 + | `RSA_PKCS1_SHA224 | `RSA_PKCS1_SHA1 | `RSA_PKCS1_MD5 294 + | `ECDSA_SECP256R1_SHA1 -> false 295 + 296 + let pk_matches_sa pk sa = 297 + match pk, sa with 298 + | `RSA _, _ -> rsa_sigalg sa 299 + | `ED25519 _, `ED25519 300 + | `P256 _, (`ECDSA_SECP256R1_SHA1 | `ECDSA_SECP256R1_SHA256) 301 + | `P384 _, `ECDSA_SECP384R1_SHA384 302 + | `P521 _, `ECDSA_SECP521R1_SHA512 -> true 303 + | _ -> false 304 + 305 + type client_extension = [ 306 + | `Hostname of [`host] Domain_name.t 307 + | `MaxFragmentLength of max_fragment_length 308 + | `SupportedGroups of Packet.named_group list 309 + | `SecureRenegotiation of string 310 + | `Padding of int 311 + | `SignatureAlgorithms of signature_algorithm list 312 + | `ExtendedMasterSecret 313 + | `ALPN of string list 314 + | `KeyShare of (Packet.named_group * string) list 315 + | `EarlyDataIndication 316 + | `PreSharedKeys of psk_identity list 317 + | `SupportedVersions of tls_any_version list 318 + | `PostHandshakeAuthentication 319 + | `Cookie of string 320 + | `PskKeyExchangeModes of psk_key_exchange_mode list 321 + | `ECPointFormats 322 + | `UnknownExtension of (int * string) 323 + ] 324 + 325 + type server13_extension = [ 326 + | `KeyShare of (group * string) 327 + | `PreSharedKey of int 328 + | `SelectedVersion of tls_version (* only used internally in writer!! *) 329 + ] 330 + 331 + type server_extension = [ 332 + server13_extension 333 + | `Hostname 334 + | `MaxFragmentLength of max_fragment_length 335 + | `SecureRenegotiation of string 336 + | `ExtendedMasterSecret 337 + | `ALPN of string 338 + | `ECPointFormats 339 + | `UnknownExtension of (int * string) 340 + ] 341 + 342 + type encrypted_extension = [ 343 + | `Hostname 344 + | `MaxFragmentLength of max_fragment_length 345 + | `SupportedGroups of group list 346 + | `ALPN of string 347 + | `EarlyDataIndication 348 + | `UnknownExtension of (int * string) 349 + ] 350 + 351 + type hello_retry_extension = [ 352 + | `SelectedGroup of group (* only used internally in writer!! *) 353 + | `Cookie of string 354 + | `SelectedVersion of tls_version (* only used internally in writer!! *) 355 + | `UnknownExtension of (int * string) 356 + ] 357 + 358 + type client_hello = { 359 + client_version : tls_any_version; 360 + client_random : string; 361 + sessionid : SessionID.t option; 362 + ciphersuites : any_ciphersuite list; 363 + extensions : client_extension list 364 + } 365 + 366 + type server_hello = { 367 + server_version : tls_version; 368 + server_random : string; 369 + sessionid : SessionID.t option; 370 + ciphersuite : ciphersuite; 371 + extensions : server_extension list 372 + } 373 + 374 + type dh_parameters = { 375 + dh_p : string; 376 + dh_g : string; 377 + dh_Ys : string; 378 + } 379 + 380 + type hello_retry = { 381 + retry_version : tls_version ; 382 + ciphersuite : ciphersuite13 ; 383 + sessionid : SessionID.t option ; 384 + selected_group : group ; 385 + extensions : hello_retry_extension list 386 + } 387 + 388 + type session_ticket_extension = [ 389 + | `EarlyDataIndication of int32 390 + | `UnknownExtension of int * string 391 + ] 392 + 393 + type session_ticket = { 394 + lifetime : int32 ; 395 + age_add : int32 ; 396 + nonce : string ; 397 + ticket : string ; 398 + extensions : session_ticket_extension list 399 + } 400 + 401 + type certificate_request_extension = [ 402 + (* | `StatusRequest *) 403 + | `SignatureAlgorithms of signature_algorithm list 404 + (* | `SignedCertificateTimestamp *) 405 + | `CertificateAuthorities of X509.Distinguished_name.t list 406 + (* | `OidFilters *) 407 + (* | `SignatureAlgorithmsCert *) 408 + | `UnknownExtension of (int * string) 409 + ] 410 + 411 + type tls_handshake = 412 + | HelloRequest 413 + | HelloRetryRequest of hello_retry 414 + | EncryptedExtensions of encrypted_extension list 415 + | ServerHelloDone 416 + | ClientHello of client_hello 417 + | ServerHello of server_hello 418 + | Certificate of string 419 + | ServerKeyExchange of string 420 + | CertificateRequest of string 421 + | ClientKeyExchange of string 422 + | CertificateVerify of string 423 + | Finished of string 424 + | SessionTicket of session_ticket 425 + | KeyUpdate of key_update_request_type 426 + | EndOfEarlyData 427 + 428 + let pp_handshake ppf = function 429 + | HelloRequest -> Fmt.string ppf "HelloRequest" 430 + | HelloRetryRequest _ -> Fmt.string ppf "HelloRetryRequest" 431 + | EncryptedExtensions _ -> Fmt.string ppf "EncryptedExtensions" 432 + | ServerHelloDone -> Fmt.string ppf "ServerHelloDone" 433 + | ClientHello _ -> Fmt.string ppf "ClientHello" 434 + | ServerHello _ -> Fmt.string ppf "ServerHello" 435 + | Certificate _ -> Fmt.string ppf "Certificate" 436 + | ServerKeyExchange _ -> Fmt.string ppf "ServerKeyExchange" 437 + | CertificateRequest _ -> Fmt.string ppf "CertificateRequest" 438 + | ClientKeyExchange _ -> Fmt.string ppf "ClientKeyExchange" 439 + | CertificateVerify _ -> Fmt.string ppf "CertificateVerify" 440 + | Finished _ -> Fmt.string ppf "Finished" 441 + | SessionTicket _ -> Fmt.string ppf "SessionTicket" 442 + | KeyUpdate _ -> Fmt.string ppf "KeyUpdate" 443 + | EndOfEarlyData -> Fmt.string ppf "EndOfEarlyData" 444 + 445 + let src = Logs.Src.create "tls.tracing" ~doc:"TLS tracing" 446 + module Tracing = struct 447 + include (val Logs.src_log src : Logs.LOG) 448 + let cs ~tag buf = debug (fun m -> m "%s@.%a" tag (Ohex.pp_hexdump ()) buf) 449 + let hs ~tag hs = debug (fun m -> m "%s %a" tag pp_handshake hs) 450 + end 451 + 452 + type tls_alert = alert_level * alert_type 453 + 454 + (** the master secret of a TLS connection *) 455 + type master_secret = string 456 + 457 + type psk13 = { 458 + identifier : string ; 459 + obfuscation : int32 ; 460 + secret : string ; 461 + lifetime : int32 ; 462 + early_data : int32 ; 463 + issued_at : Ptime.t ; 464 + (* origin : [ `Resumption | `External ] (* using different labels for binder_key *) *) 465 + } 466 + 467 + type epoch_state = [ `ZeroRTT | `Established ] 468 + 469 + (** information about an open session *) 470 + type epoch_data = { 471 + side : [ `Client | `Server ] ; 472 + state : epoch_state ; 473 + protocol_version : tls_version ; 474 + ciphersuite : Ciphersuite.ciphersuite ; 475 + peer_random : string ; 476 + peer_certificate_chain : X509.Certificate.t list ; 477 + peer_certificate : X509.Certificate.t option ; 478 + peer_name : [`host] Domain_name.t option ; 479 + trust_anchor : X509.Certificate.t option ; 480 + received_certificates : X509.Certificate.t list ; 481 + own_random : string ; 482 + own_certificate : X509.Certificate.t list ; 483 + own_private_key : X509.Private_key.t option ; 484 + own_name : [`host] Domain_name.t option ; 485 + master_secret : master_secret ; 486 + exporter_master_secret : master_secret ; 487 + session_id : SessionID.t ; 488 + extended_ms : bool ; 489 + alpn_protocol : string option ; 490 + tls_unique : string option ; 491 + } 492 + 493 + let supports_key_usage ?(not_present = false) usage cert = 494 + match X509.Extension.(find Key_usage (X509.Certificate.extensions cert)) with 495 + | None -> not_present 496 + | Some (_, kus) -> List.mem usage kus 497 + 498 + let supports_extended_key_usage ?(not_present = false) usage cert = 499 + match X509.Extension.(find Ext_key_usage (X509.Certificate.extensions cert)) with 500 + | None -> not_present 501 + | Some (_, kus) -> List.mem usage kus
+159
vendor/opam/tls/lib/crypto.ml
··· 1 + open Mirage_crypto 2 + 3 + open Ciphersuite 4 + 5 + (* on-the-wire dh_params <-> (group, pub_message) *) 6 + let dh_params_pack { Mirage_crypto_pk.Dh.p; gg ; _ } message = 7 + let cs_of_z = Mirage_crypto_pk.Z_extra.to_octets_be ?size:None in 8 + { Core.dh_p = cs_of_z p ; dh_g = cs_of_z gg ; dh_Ys = message } 9 + 10 + and dh_params_unpack { Core.dh_p ; dh_g ; dh_Ys } = 11 + let z_of_cs = Mirage_crypto_pk.Z_extra.of_octets_be ?bits:None in 12 + match Mirage_crypto_pk.Dh.group ~p:(z_of_cs dh_p) ~gg:(z_of_cs dh_g) () with 13 + | Ok dh -> Ok (dh, dh_Ys) 14 + | Error _ as e -> e 15 + 16 + module Ciphers = struct 17 + 18 + (* I'm not sure how to get rid of this type, but would welcome a solution *) 19 + (* only used as result of get_block, which is called by get_cipher below *) 20 + type keyed = | K_CBC : 'k State.cbc_cipher * (string -> 'k) -> keyed 21 + 22 + let get_block = function 23 + | TRIPLE_DES_EDE_CBC -> 24 + K_CBC ( (module DES.CBC : Block.CBC with type key = DES.CBC.key), 25 + DES.CBC.of_secret ) 26 + 27 + | AES_128_CBC -> 28 + K_CBC ( (module AES.CBC : Block.CBC with type key = AES.CBC.key), 29 + AES.CBC.of_secret ) 30 + 31 + | AES_256_CBC -> 32 + K_CBC ( (module AES.CBC : Block.CBC with type key = AES.CBC.key), 33 + AES.CBC.of_secret ) 34 + 35 + type aead_keyed = | K_AEAD : 'k State.aead_cipher * (string -> 'k) * bool -> aead_keyed 36 + let get_aead = 37 + function 38 + | AES_128_CCM | AES_256_CCM -> 39 + K_AEAD ((module AES.CCM16 : AEAD with type key = AES.CCM16.key), 40 + AES.CCM16.of_secret, true) 41 + | AES_128_GCM | AES_256_GCM -> 42 + K_AEAD ((module AES.GCM : AEAD with type key = AES.GCM.key), 43 + AES.GCM.of_secret, true) 44 + | CHACHA20_POLY1305 -> 45 + K_AEAD ((module Chacha20 : AEAD with type key = Chacha20.key), 46 + Chacha20.of_secret, false) 47 + 48 + let get_aead_cipher ~secret ~nonce aead_cipher = 49 + match get_aead aead_cipher with 50 + | K_AEAD (cipher, sec, explicit_nonce) -> 51 + let cipher_secret = sec secret in 52 + State.(AEAD { cipher ; cipher_secret ; nonce ; explicit_nonce }) 53 + 54 + let get_cipher ~secret ~hmac_secret ~iv_mode ~nonce = function 55 + | `Block (cipher, hmac) -> 56 + ( match get_block cipher with 57 + | K_CBC (cipher, sec) -> 58 + let cipher_secret = sec secret in 59 + State.(CBC { cipher ; cipher_secret ; iv_mode ; hmac ; hmac_secret }) 60 + ) 61 + 62 + | `AEAD cipher -> get_aead_cipher ~secret ~nonce cipher 63 + end 64 + 65 + let sequence_buf seq = 66 + let buf = Bytes.create 8 in 67 + Bytes.set_int64_be buf 0 seq ; 68 + Bytes.unsafe_to_string buf 69 + 70 + let aead_nonce nonce seq = 71 + let s = 72 + let l = String.length nonce in 73 + let buf = Bytes.make l '\x00' in 74 + Bytes.set_int64_be buf (l - 8) seq; 75 + Bytes.unsafe_to_string buf 76 + in 77 + Uncommon.xor nonce s 78 + 79 + let adata_1_3 len = 80 + (* additional data in TLS 1.3 is using the header (RFC 8446 Section 5.2): 81 + - APPLICATION_TYPE 82 + - 0x03 0x03 (for TLS version 1.2 -- binary representation is 0x03 0x03) 83 + - <length in 16 bit> 84 + *) 85 + let buf = Bytes.create 5 in 86 + Bytes.set_uint8 buf 0 (Packet.content_type_to_int Packet.APPLICATION_DATA) ; 87 + Bytes.set_uint8 buf 1 3; 88 + Bytes.set_uint8 buf 2 3; 89 + Bytes.set_uint16_be buf 3 len ; 90 + Bytes.unsafe_to_string buf 91 + 92 + let pseudo_header seq ty (v_major, v_minor) v_length = 93 + let buf = Bytes.create 13 in 94 + Bytes.set_int64_be buf 0 seq; 95 + Bytes.set_uint8 buf 8 (Packet.content_type_to_int ty); 96 + Bytes.set_uint8 buf 9 v_major; 97 + Bytes.set_uint8 buf 10 v_minor; 98 + Bytes.set_uint16_be buf 11 v_length; 99 + Bytes.unsafe_to_string buf 100 + 101 + (* MAC used in TLS *) 102 + let mac hash key pseudo_hdr data = 103 + let module H = (val Digestif.module_of_hash' hash) in 104 + H.(to_raw_string (hmacv_string ~key [ pseudo_hdr ; data ])) 105 + 106 + let cbc_block (type a) cipher = 107 + let module C = (val cipher : Block.CBC with type key = a) in C.block_size 108 + 109 + (* crazy CBC padding and unpadding for TLS *) 110 + let cbc_pad block data = 111 + (* 1 is the padding length, encoded as 8 bit at the end of the fragment *) 112 + let len = 1 + String.length data in 113 + (* we might want to add additional blocks of padding *) 114 + let padding_length = block - (len mod block) in 115 + (* 1 is again padding length field *) 116 + let cstruct_len = padding_length + 1 in 117 + String.make cstruct_len (Char.unsafe_chr padding_length) 118 + 119 + let cbc_unpad data = 120 + let len = String.length data in 121 + let padlen = String.get_uint8 data (pred len) in 122 + 123 + let rec check = function 124 + | i when i > padlen -> true 125 + | i -> (String.get_uint8 data (len - padlen - 1 + i) = padlen) && check (succ i) in 126 + 127 + try 128 + if check 0 then Some (String.sub data 0 (len - padlen - 1)) else None 129 + with Invalid_argument _ -> None 130 + 131 + let tag_len (type a) cipher = 132 + let module C = (val cipher : AEAD with type key = a) in 133 + C.tag_size 134 + 135 + let encrypt_aead (type a) ~cipher ~key ~nonce ?adata data = 136 + let module C = (val cipher : AEAD with type key = a) in 137 + C.authenticate_encrypt ~key ~nonce ?adata data 138 + 139 + let decrypt_aead (type a) ~cipher ~key ~nonce ?adata data = 140 + let module C = (val cipher : AEAD with type key = a) in 141 + C.authenticate_decrypt ~key ~nonce ?adata data 142 + 143 + let encrypt_cbc (type a) ~cipher ~key ~iv data = 144 + let module C = (val cipher : Block.CBC with type key = a) in 145 + let message = C.encrypt ~key ~iv (data ^ cbc_pad C.block_size data) in 146 + (message, C.next_iv ~iv message) 147 + 148 + let decrypt_cbc (type a) ~cipher ~key ~iv data = 149 + let module C = (val cipher : Block.CBC with type key = a) in 150 + try 151 + let message = C.decrypt ~key ~iv data in 152 + match cbc_unpad message with 153 + | Some res -> Some (res, C.next_iv ~iv data) 154 + | None -> None 155 + with 156 + (* This bails out immediately on mis-alignment, making it very timeable. 157 + * However, decryption belongs to the outermost level and this operation's 158 + * timing does not leak information ala padding oracle and friends. *) 159 + | Invalid_argument _ -> None
+5
vendor/opam/tls/lib/dune
··· 1 + (library 2 + (name tls) 3 + (public_name tls) 4 + (libraries logs kdf.hkdf ohex digestif mirage-crypto mirage-crypto-rng 5 + mirage-crypto-pk x509 domain-name fmt mirage-crypto-ec ipaddr))
+761
vendor/opam/tls/lib/engine.ml
··· 1 + open Core 2 + open State 3 + 4 + type state = State.state 5 + 6 + type error = State.error 7 + type fatal = State.fatal 8 + type failure = State.failure 9 + 10 + let alert_of_authentication_failure = function 11 + | `LeafCertificateExpired _ -> Packet.CERTIFICATE_EXPIRED 12 + | _ -> Packet.BAD_CERTIFICATE 13 + 14 + let alert_of_error = function 15 + | `NoConfiguredVersions _ -> Packet.PROTOCOL_VERSION 16 + | `NoConfiguredCiphersuite _ -> Packet.HANDSHAKE_FAILURE 17 + | `NoConfiguredSignatureAlgorithm _ -> Packet.HANDSHAKE_FAILURE 18 + | `AuthenticationFailure err -> alert_of_authentication_failure err 19 + | `NoMatchingCertificateFound _ -> Packet.UNRECOGNIZED_NAME 20 + | `CouldntSelectCertificate -> Packet.HANDSHAKE_FAILURE 21 + 22 + let alert_of_fatal = function 23 + | `Protocol_version _ -> Packet.PROTOCOL_VERSION 24 + | `Unexpected _ -> Packet.UNEXPECTED_MESSAGE 25 + | `Decode _ -> Packet.DECODE_ERROR 26 + | `Handshake _ -> Packet.HANDSHAKE_FAILURE 27 + | `Bad_mac -> Packet.BAD_RECORD_MAC 28 + | `Record_overflow _ -> Packet.RECORD_OVERFLOW 29 + | `Unsupported_extension -> Packet.UNSUPPORTED_EXTENSION 30 + | `Bad_certificate _ -> Packet.BAD_CERTIFICATE 31 + | `Missing_extension _ -> Packet.MISSING_EXTENSION 32 + | `Inappropriate_fallback -> Packet.INAPPROPRIATE_FALLBACK 33 + | `No_application_protocol -> Packet.NO_APPLICATION_PROTOCOL 34 + 35 + let alert_of_failure = function 36 + | `Error x -> Packet.FATAL, alert_of_error x 37 + | `Fatal x -> Packet.FATAL, alert_of_fatal x 38 + | `Alert _ -> Packet.WARNING, Packet.CLOSE_NOTIFY 39 + 40 + let pp_failure = State.pp_failure 41 + 42 + let string_of_failure = Fmt.to_to_string pp_failure 43 + 44 + type ret = 45 + (state * [ `Eof ] option 46 + * [ `Response of string option ] 47 + * [ `Data of string option ], 48 + failure * [ `Response of string ]) result 49 + 50 + let new_state config role = 51 + let handshake_state = match role with 52 + | `Client -> Client ClientInitial 53 + | `Server -> Server AwaitClientHello 54 + in 55 + let version = max_protocol_version Config.(config.protocol_versions) in 56 + let handshake = { 57 + session = [] ; 58 + protocol_version = version ; 59 + early_data_left = 0l ; 60 + machina = handshake_state ; 61 + config = config ; 62 + hs_fragment = "" ; 63 + } 64 + in 65 + { 66 + handshake = handshake ; 67 + decryptor = None ; 68 + encryptor = None ; 69 + fragment = "" ; 70 + read_closed = false ; 71 + write_closed = false ; 72 + } 73 + 74 + type raw_record = tls_hdr * string 75 + 76 + let pp_raw_record ppf (hdr, data) = 77 + Fmt.pf ppf "%a (%u bytes data)" pp_tls_hdr hdr (String.length data) 78 + 79 + let pp_frame ppf (ty, data) = 80 + Fmt.pf ppf "%a (%u bytes data)" Packet.pp_content_type ty 81 + (String.length data) 82 + 83 + (* well-behaved pure encryptor *) 84 + let encrypt (version : tls_version) (st : crypto_state) ty buf off len = 85 + match st with 86 + | None -> (st, ty, String.sub buf off len) 87 + | Some ctx -> 88 + match version with 89 + | `TLS_1_3 -> 90 + (match ctx.cipher_st with 91 + | AEAD c -> 92 + let buf = 93 + let b = Bytes.create (len + 1) in 94 + Bytes.set_uint8 b len (Packet.content_type_to_int ty); 95 + Bytes.blit_string buf off b 0 len; 96 + Bytes.unsafe_to_string b 97 + in 98 + let nonce = Crypto.aead_nonce c.nonce ctx.sequence in 99 + let adata = Crypto.adata_1_3 (String.length buf + Crypto.tag_len c.cipher) in 100 + let buf = Crypto.encrypt_aead ~cipher:c.cipher ~adata ~key:c.cipher_secret ~nonce buf in 101 + (Some { ctx with sequence = Int64.succ ctx.sequence }, Packet.APPLICATION_DATA, buf) 102 + | _ -> assert false) 103 + | _ -> 104 + let pseudo_hdr = 105 + let seq = ctx.sequence 106 + and ver = pair_of_tls_version version 107 + in 108 + Crypto.pseudo_header seq ty ver len 109 + in 110 + let c_st, enc = 111 + match ctx.cipher_st with 112 + | CBC c -> 113 + let enc iv = 114 + (* TODO only until digestif goes beyond 1.2.0 (feedable hmac) *) 115 + let data = String.sub buf off len in 116 + let signature = Crypto.mac c.hmac c.hmac_secret pseudo_hdr buf in 117 + let to_encrypt = data ^ signature in 118 + Crypto.encrypt_cbc ~cipher:c.cipher ~key:c.cipher_secret ~iv to_encrypt 119 + in 120 + ( match c.iv_mode with 121 + | Random_iv -> 122 + let iv = Mirage_crypto_rng.generate (Crypto.cbc_block c.cipher) in 123 + let m, _ = enc iv in 124 + (CBC c, iv ^ m) 125 + | Iv iv -> 126 + let m, iv' = enc iv in 127 + (CBC { c with iv_mode = Iv iv' }, m) ) 128 + | AEAD c -> 129 + let buf = String.sub buf off len in 130 + if c.explicit_nonce then 131 + let explicit_nonce = Crypto.sequence_buf ctx.sequence in 132 + let nonce = c.nonce ^ explicit_nonce 133 + in 134 + let msg = 135 + Crypto.encrypt_aead ~cipher:c.cipher ~key:c.cipher_secret ~nonce ~adata:pseudo_hdr buf 136 + in 137 + (AEAD c, explicit_nonce ^ msg) 138 + else 139 + (* RFC 7905: no explicit nonce, instead TLS 1.3 construction is adapted *) 140 + let nonce = Crypto.aead_nonce c.nonce ctx.sequence in 141 + let msg = 142 + Crypto.encrypt_aead ~cipher:c.cipher ~key:c.cipher_secret ~nonce ~adata:pseudo_hdr buf 143 + in 144 + (AEAD c, msg) 145 + in 146 + (Some { sequence = Int64.succ ctx.sequence ; cipher_st = c_st }, ty, enc) 147 + 148 + (* well-behaved pure decryptor *) 149 + let verify_mac sequence mac mac_k ty ver decrypted = 150 + let macstart = 151 + let module H = (val Digestif.module_of_hash' mac) in 152 + String.length decrypted - H.digest_size 153 + in 154 + let* () = guard (macstart >= 0) (`Fatal (`Decode "MAC underflow")) in 155 + let (body, mmac) = split_str decrypted macstart in 156 + let cmac = 157 + let ver = pair_of_tls_version ver in 158 + let hdr = Crypto.pseudo_header sequence ty ver (String.length body) in 159 + Crypto.mac mac mac_k hdr body in 160 + let* () = guard (String.equal cmac mmac) (`Fatal `Bad_mac) in 161 + Ok body 162 + 163 + 164 + let decrypt ?(trial = false) (version : tls_version) (st : crypto_state) ty buf = 165 + 166 + let compute_mac seq mac mac_k buf = verify_mac seq mac mac_k ty version buf in 167 + (* hmac is computed in this failure branch from the encrypted data, in the 168 + successful branch it is decrypted - padding (which is smaller equal than 169 + encrypted data) *) 170 + (* This comment is borrowed from miTLS, but applies here as well: *) 171 + (* We implement standard mitigation for padding oracles. Still, we note a 172 + small timing leak here: The time to verify the mac is linear in the 173 + plaintext length. *) 174 + (* defense against http://lasecwww.epfl.ch/memo/memo_ssl.shtml 1) in 175 + https://www.openssl.org/~bodo/tls-cbc.txt *) 176 + let mask_decrypt_failure seq mac mac_k = 177 + let* _ = compute_mac seq mac mac_k buf in 178 + Error (`Fatal `Bad_mac) 179 + in 180 + 181 + let dec ctx = 182 + let seq = ctx.sequence in 183 + match ctx.cipher_st with 184 + | CBC c -> 185 + let dec iv buf = 186 + match Crypto.decrypt_cbc ~cipher:c.cipher ~key:c.cipher_secret ~iv buf with 187 + | None -> 188 + mask_decrypt_failure seq c.hmac c.hmac_secret 189 + | Some (dec, iv') -> 190 + let* msg = compute_mac seq c.hmac c.hmac_secret dec in 191 + Ok (msg, iv') 192 + in 193 + ( match c.iv_mode with 194 + | Iv iv -> 195 + let* msg, iv' = dec iv buf in 196 + Ok (CBC { c with iv_mode = Iv iv' }, msg) 197 + | Random_iv -> 198 + if String.length buf < Crypto.cbc_block c.cipher then 199 + Error (`Fatal (`Decode "MAC underflow")) 200 + else 201 + let iv, buf = split_str buf (Crypto.cbc_block c.cipher) in 202 + let* msg, _ = dec iv buf in 203 + Ok (CBC c, msg) ) 204 + 205 + | AEAD c -> 206 + if c.explicit_nonce then 207 + let explicit_nonce_len = 8 in 208 + if String.length buf < explicit_nonce_len then 209 + Error (`Fatal (`Decode "MAC underflow")) 210 + else 211 + let explicit_nonce, buf = split_str buf explicit_nonce_len in 212 + let adata = 213 + let ver = pair_of_tls_version version in 214 + Crypto.pseudo_header seq ty ver (String.length buf - Crypto.tag_len c.cipher) 215 + and nonce = c.nonce ^ explicit_nonce 216 + in 217 + match Crypto.decrypt_aead ~cipher:c.cipher ~key:c.cipher_secret ~nonce ~adata buf with 218 + | None -> Error (`Fatal `Bad_mac) 219 + | Some x -> Ok (AEAD c, x) 220 + else 221 + (* RFC 7905: no explicit nonce, instead TLS 1.3 construction is adapted *) 222 + let adata = 223 + let ver = pair_of_tls_version version in 224 + Crypto.pseudo_header seq ty ver (String.length buf - Crypto.tag_len c.cipher) 225 + and nonce = Crypto.aead_nonce c.nonce seq 226 + in 227 + (match Crypto.decrypt_aead ~adata ~cipher:c.cipher ~key:c.cipher_secret ~nonce buf with 228 + | None -> Error (`Fatal `Bad_mac) 229 + | Some x -> Ok (AEAD c, x)) 230 + in 231 + match st, version with 232 + | None, _ when ty = Packet.APPLICATION_DATA -> 233 + (* the server can end up in the situation: 234 + CH [+early_data +key_share] ; APP_DATA ----> 235 + <--- HRR [+key_share] (does not install a decryptor, 236 + early data now disallowed) 237 + CH [+key_share] -----> 238 + the APP_DATA above cannot be decrypted or used, so we drop it. 239 + *) 240 + Ok (None, "", Packet.APPLICATION_DATA) 241 + | None, _ -> Ok (st, buf, ty) 242 + | Some ctx, `TLS_1_3 -> 243 + (match ty with 244 + | Packet.CHANGE_CIPHER_SPEC -> Ok (st, buf, ty) 245 + | Packet.APPLICATION_DATA -> 246 + (match ctx.cipher_st with 247 + | AEAD c -> 248 + let nonce = Crypto.aead_nonce c.nonce ctx.sequence in 249 + let unpad x = 250 + let rec eat = function 251 + | -1 -> Error (`Fatal (`Unexpected (`Message "missing content type"))) 252 + | idx -> match String.get_uint8 x idx with 253 + | 0 -> eat (pred idx) 254 + | n -> match Packet.int_to_content_type n with 255 + | Some ct -> Ok (String.sub x 0 idx, ct) 256 + | None -> Error (`Fatal (`Unexpected (`Content_type n))) 257 + in 258 + eat (pred (String.length x)) 259 + in 260 + let adata = Crypto.adata_1_3 (String.length buf) in 261 + (match Crypto.decrypt_aead ~adata ~cipher:c.cipher ~key:c.cipher_secret ~nonce buf with 262 + | None -> 263 + if trial then 264 + Ok (Some ctx, "", Packet.APPLICATION_DATA) 265 + else 266 + Error (`Fatal `Bad_mac) 267 + | Some x -> 268 + let* data, ty = unpad x in 269 + Ok (Some { ctx with sequence = Int64.succ ctx.sequence }, data, ty)) 270 + | _ -> Error (`Fatal (`Handshake (`Message "unexpected cipher state (must be AEAD)")))) 271 + | ct -> 272 + let msg = "unexpected content type (TLS 1.3, encrypted) " ^ Packet.content_type_to_string ct in 273 + Error (`Fatal (`Handshake (`Message msg)))) 274 + | Some ctx, _ -> 275 + let* st', msg = dec ctx in 276 + let ctx' = { cipher_st = st' ; sequence = Int64.succ ctx.sequence } in 277 + Ok (Some ctx', msg, ty) 278 + 279 + (* party time *) 280 + let rec separate_records : string -> ((tls_hdr * string) list * string, failure) result 281 + = fun buf -> 282 + match Reader.parse_record buf with 283 + | Ok (`Fragment b) -> Ok ([], b) 284 + | Ok (`Record (packet, fragment)) -> 285 + let* tl, frag = separate_records fragment in 286 + Ok (packet :: tl, frag) 287 + | Error e -> 288 + Tracing.cs ~tag:"buf-in" buf ; 289 + Error (`Fatal e) 290 + 291 + let encrypt_records encryptor version records = 292 + let rec crypt st acc = function 293 + | [] -> st, List.rev acc 294 + | (ty, buf) :: rest -> 295 + let bufl = String.length buf in 296 + let rec doit st acc off = 297 + if bufl - off >= 1 lsl 14 then 298 + let len = 1 lsl 14 in 299 + let st, ty, buf = encrypt version st ty buf off len in 300 + (doit [@tailcall]) st ((ty, buf) :: acc) (off + len) 301 + else 302 + let st, ty, buf = encrypt version st ty buf off (bufl - off) in 303 + st, (ty, buf) :: acc 304 + in 305 + let st, res = doit st [] 0 in 306 + (crypt [@tailcall]) st (res @ acc) rest 307 + in 308 + crypt encryptor [] records 309 + 310 + module Alert = struct 311 + (* The alert protocol: 312 + - receiving a close_notify leads to eof (never read() any further data) 313 + - any fatal alert leads to sending a close_notify and state is closed 314 + *) 315 + 316 + open Packet 317 + 318 + let make ?level typ = (ALERT, Writer.assemble_alert ?level typ) 319 + 320 + let close_notify = make ~level:WARNING CLOSE_NOTIFY 321 + 322 + let handle buf = 323 + let* alert = map_reader_error (Reader.parse_alert buf) in 324 + let _, a_type = alert in 325 + Tracing.debug (fun m -> m "alert-in %a" pp_alert alert) ; 326 + match a_type with 327 + | CLOSE_NOTIFY | USER_CANCELED -> Ok true 328 + | _ -> Error (`Alert a_type) 329 + end 330 + 331 + let hs_can_handle_appdata s = 332 + (* When is a TLS session up for some application data? 333 + - initial handshake must be finished! 334 + - renegotiation must not be in progress 335 + --> thus only ok for Established 336 + - but ok if server sent a HelloRequest and can get first some appdata then ClientHello 337 + --> or converse: client sent ClientHello, waiting for ServerHello *) 338 + (* turns out, rules in 1.3 are slightly different -- server may send appdata after its first flight! 339 + this means in any observable state! (apart from when a HRR was sent) *) 340 + match s.machina with 341 + | Server13 AwaitClientHelloHRR13 -> false 342 + | Server Established | Server AwaitClientHelloRenegotiate | Server13 _ 343 + | Client Established | Client AwaitServerHelloRenegotiate _ | Client13 Established13 -> true 344 + | _ -> false 345 + 346 + let early_data s = 347 + match s.machina with 348 + | Server13 AwaitClientHelloHRR13 349 + | Server13 (AwaitEndOfEarlyData13 _) | Server13 (AwaitClientFinished13 _) 350 + | Server13 (AwaitClientCertificate13 _) | Server13 (AwaitClientCertificateVerify13 _) -> true 351 + | _ -> false 352 + 353 + let rec separate_handshakes buf = 354 + match Reader.parse_handshake_frame buf with 355 + | None, rest -> [], rest 356 + | Some hs, rest -> 357 + let rt, frag = separate_handshakes rest in 358 + hs :: rt, frag 359 + 360 + let handle_change_cipher_spec = function 361 + | Client cs -> Handshake_client.handle_change_cipher_spec cs 362 + | Server ss -> Handshake_server.handle_change_cipher_spec ss 363 + (* D.4: the client may send a CCS before its second flight 364 + (before second ClientHello or encrypted handshake flight) 365 + the server may send it immediately after its first handshake message 366 + (ServerHello or HelloRetryRequest) *) 367 + | Client13 (AwaitServerEncryptedExtensions13 _) 368 + | Client13 (AwaitServerHello13 _) 369 + | Server13 AwaitClientHelloHRR13 370 + | Server13 (AwaitClientCertificate13 _) 371 + | Server13 (AwaitClientFinished13 _) -> (fun s _ -> Ok (s, [])) 372 + | _ -> (fun _ _ -> Error (`Fatal (`Unexpected (`Message "change cipher spec")))) 373 + 374 + and handle_handshake = function 375 + | Client cs -> Handshake_client.handle_handshake cs 376 + | Server ss -> Handshake_server.handle_handshake ss 377 + | Client13 cs -> Handshake_client13.handle_handshake cs 378 + | Server13 ss -> Handshake_server13.handle_handshake ss 379 + 380 + let non_empty cs = 381 + if String.length cs = 0 then None else Some cs 382 + 383 + let handle_packet hs buf = function 384 + (* RFC 5246 -- 6.2.1.: 385 + Implementations MUST NOT send zero-length fragments of Handshake, 386 + Alert, or ChangeCipherSpec content types. Zero-length fragments of 387 + Application data MAY be sent as they are potentially useful as a 388 + traffic analysis countermeasure. 389 + *) 390 + 391 + | Packet.ALERT -> 392 + let* eof = Alert.handle buf in 393 + Ok (hs, [], None, eof) 394 + 395 + | Packet.APPLICATION_DATA -> 396 + if hs_can_handle_appdata hs || (early_data hs && String.length hs.hs_fragment = 0) then 397 + (Tracing.cs ~tag:"application-data-in" buf; 398 + Ok (hs, [], non_empty buf, false)) 399 + else 400 + Error (`Fatal (`Unexpected (`Message "application data"))) 401 + 402 + | Packet.CHANGE_CIPHER_SPEC -> 403 + let* hs, items = handle_change_cipher_spec hs.machina hs buf in 404 + Ok (hs, items, None, false) 405 + 406 + | Packet.HANDSHAKE -> 407 + let hss, hs_fragment = separate_handshakes (hs.hs_fragment ^ buf) in 408 + let hs = { hs with hs_fragment } in 409 + let* hs, items = 410 + List.fold_left (fun acc raw -> 411 + let* hs, items = acc in 412 + let* hs', items' = handle_handshake hs.machina hs raw in 413 + Ok (hs', items @ items')) 414 + (Ok (hs, [])) hss 415 + in 416 + Ok (hs, items, None, false) 417 + 418 + let decrement_early_data hs ty buf = 419 + let bytes left cipher = 420 + let count = String.length buf - fst (Ciphersuite.kn_13 (Ciphersuite.privprot13 cipher)) in 421 + let left' = Int32.sub left (Int32.of_int count) in 422 + if left' < 0l then 423 + Error (`Fatal (`Unexpected (`Message "too many 0RTT bytes"))) 424 + else 425 + Ok left' 426 + in 427 + if ty = Packet.APPLICATION_DATA && early_data hs then 428 + let cipher = match hs.session with 429 + | `TLS13 sd::_ -> sd.ciphersuite13 430 + | _ -> `AES_128_GCM_SHA256 431 + (* TODO assert and ensure that all early_data states have a cipher *) 432 + in 433 + let* early_data_left = bytes hs.early_data_left cipher in 434 + Ok { hs with early_data_left } 435 + else 436 + Ok hs 437 + 438 + (* the main thingy *) 439 + let handle_raw_record state (hdr, buf as record : raw_record) = 440 + 441 + Tracing.debug (fun m -> m "record-in %a" pp_raw_record record) ; 442 + let hs = state.handshake in 443 + let version = hs.protocol_version in 444 + let* () = 445 + match hs.machina, version with 446 + | Client (AwaitServerHello _), _ -> Ok () 447 + | Server AwaitClientHello, _ -> Ok () 448 + | Server13 AwaitClientHelloHRR13, _ -> Ok () 449 + | _, `TLS_1_3 -> 450 + guard (hdr.version = `TLS_1_2) 451 + (`Fatal (`Protocol_version (`Bad_record hdr.version))) 452 + | _, v -> 453 + guard (version_eq hdr.version v) 454 + (`Fatal (`Protocol_version (`Bad_record hdr.version))) 455 + in 456 + let trial = match hs.machina with 457 + | Server13 (AwaitEndOfEarlyData13 _) | Server13 Established13 -> false 458 + | Server13 _ -> hs.early_data_left > 0l && String.length hs.hs_fragment = 0 459 + | _ -> false 460 + in 461 + let* dec_st, dec, ty = decrypt ~trial version state.decryptor hdr.content_type buf in 462 + let* handshake = decrement_early_data hs ty buf in 463 + Tracing.debug (fun m -> m "frame-in %a" pp_frame (ty, dec)) ; 464 + let* handshake, items, data, read_closed = handle_packet handshake dec ty in 465 + let encryptor, decryptor, encs = 466 + List.fold_left (fun (enc, dec, es) -> function 467 + | `Change_enc enc' -> (Some enc', dec, es) 468 + | `Change_dec dec' -> (enc, Some dec', es) 469 + | `Record r -> 470 + Tracing.debug (fun m -> m "frame-out %a" pp_frame r) ; 471 + let (enc', encbuf) = encrypt_records enc handshake.protocol_version [r] in 472 + (enc', dec, es @ encbuf)) 473 + (state.encryptor, dec_st, []) 474 + items 475 + in 476 + List.iter (fun f -> Tracing.debug (fun m -> m "record-out %a" pp_frame f)) encs ; 477 + let read_closed = read_closed || state.read_closed in 478 + let state' = { state with handshake ; encryptor ; decryptor ; read_closed } in 479 + Ok (state', encs, data) 480 + 481 + let maybe_app a b = match a, b with 482 + | Some x, Some y -> Some (x ^ y) 483 + | Some x, None -> Some x 484 + | None , Some y -> Some y 485 + | None , None -> None 486 + 487 + let assemble_records (version : tls_version) rs = 488 + let version = match version with `TLS_1_3 -> `TLS_1_2 | x -> x in 489 + String.concat "" (List.map (Writer.assemble_hdr version) rs) 490 + 491 + (* main entry point *) 492 + let handle_tls state buf = 493 + Tracing.cs ~tag:"wire-in" buf ; 494 + 495 + let rec handle_records st = function 496 + | [] -> Ok (st, [], None) 497 + | r::rs -> 498 + let* st, raw_rs, data = handle_raw_record st r in 499 + let* st', raw_rs', data' = handle_records st rs in 500 + Ok (st', raw_rs @ raw_rs', maybe_app data data') 501 + in 502 + match 503 + let* in_records, fragment = separate_records (state.fragment ^ buf) in 504 + let* state', out_records, data = handle_records state in_records in 505 + let version = state'.handshake.protocol_version in 506 + let resp = match out_records with 507 + | [] -> None 508 + | _ -> 509 + let out = assemble_records version out_records in 510 + Tracing.cs ~tag:"wire-out" out ; 511 + Some out 512 + in 513 + Ok ({ state' with fragment }, resp, data) 514 + with 515 + | Ok (state, resp, data) -> 516 + let res = 517 + if state.read_closed then begin 518 + Tracing.debug (fun m -> m "eof-out") ; 519 + Some `Eof 520 + end else 521 + None 522 + in 523 + (* Tracing.sexpf ~tag:"state-out" ~f:sexp_of_state state ; *) 524 + Ok (state, res, `Response resp, `Data data) 525 + | Error x -> 526 + let version = state.handshake.protocol_version in 527 + let level, alert = alert_of_failure x in 528 + let record = Alert.make ~level alert in 529 + let _, enc = encrypt_records state.encryptor version [record] in 530 + let resp = assemble_records version enc in 531 + Tracing.debug (fun m -> m "fail-alert-out %a" Packet.pp_alert (Packet.FATAL, alert)) ; 532 + Tracing.debug (fun m -> m "failure %a" pp_failure x) ; 533 + Error (x, `Response resp) 534 + 535 + let send_records (st : state) records = 536 + let version = st.handshake.protocol_version in 537 + List.iter (fun f -> Tracing.debug (fun m -> m "frame-out %a" pp_frame f)) records ; 538 + let (encryptor, encs) = 539 + encrypt_records st.encryptor version records in 540 + List.iter (fun f -> Tracing.debug (fun m -> m "record-out %a" pp_frame f)) encs ; 541 + let data = assemble_records version encs in 542 + Tracing.cs ~tag:"wire-out" data ; 543 + ({ st with encryptor }, data) 544 + 545 + let handshake_in_progress s = match s.handshake.machina with 546 + | Client Established | Server Established -> false 547 + | Client13 Established13 | Server13 Established13 -> false 548 + | _ -> true 549 + 550 + (* entry for user data *) 551 + let send_application_data st css = 552 + if st.write_closed || not (hs_can_handle_appdata st.handshake) then 553 + None 554 + else begin 555 + List.iter (fun cs -> Tracing.cs ~tag:"application-data-out" cs) css ; 556 + let datas = match st.encryptor with 557 + (* Mitigate implicit IV in CBC mode: prepend empty fragment *) 558 + | Some { cipher_st = CBC { iv_mode = Iv _ ; _ } ; _ } -> "" :: css 559 + | _ -> css 560 + in 561 + let ty = Packet.APPLICATION_DATA in 562 + let data = List.map (fun cs -> (ty, cs)) datas in 563 + Some (send_records st data) 564 + end 565 + 566 + let send_close_notify st = 567 + let st = { st with write_closed = true } in 568 + send_records st [Alert.close_notify] 569 + 570 + let reneg ?authenticator ?acceptable_cas ?cert st = 571 + if st.write_closed || st.read_closed then 572 + (* this is a full handshake (with messages from both sides), thus if either 573 + direction has closed the flow, the reneg won't succeed *) 574 + None 575 + else 576 + let config = st.handshake.config in 577 + let config = Option.fold ~none:config ~some:(Config.with_authenticator config) authenticator in 578 + let config = Option.fold ~none:config ~some:(Config.with_acceptable_cas config) acceptable_cas in 579 + let config = Option.fold ~none:config ~some:(Config.with_own_certificates config) cert in 580 + let hs = { st.handshake with config } in 581 + match hs.machina with 582 + | Server Established -> 583 + ( match Handshake_server.hello_request hs with 584 + | Ok (handshake, [`Record hr]) -> Some (send_records { st with handshake } [hr]) 585 + | _ -> None ) 586 + | Client Established -> 587 + ( match Handshake_client.answer_hello_request hs with 588 + | Ok (handshake, [`Record ch]) -> Some (send_records { st with handshake } [ch]) 589 + | _ -> None ) 590 + | _ -> None 591 + 592 + let key_update ?(request = true) state = 593 + if state.write_closed then 594 + Error (`Fatal (`Unexpected (`Message "write half already closed"))) 595 + else 596 + let* state', out = Handshake_common.output_key_update ~request state in 597 + let _, outbuf = send_records state [out] in 598 + Ok (state', outbuf) 599 + 600 + let client config = 601 + let config = Config.of_client config in 602 + let state = new_state config `Client in 603 + let dch, _version, secrets = Handshake_client.default_client_hello config in 604 + let ciphers, extensions = match config.Config.protocol_versions with 605 + (* from RFC 5746 section 3.3: 606 + Both the SSLv3 and TLS 1.0/TLS 1.1 specifications require 607 + implementations to ignore data following the ClientHello (i.e., 608 + extensions) if they do not understand it. However, some SSLv3 and 609 + TLS 1.0 implementations incorrectly fail the handshake in such a 610 + case. This means that clients that offer the "renegotiation_info" 611 + extension may encounter handshake failures. In order to enhance 612 + compatibility with such servers, this document defines a second 613 + signaling mechanism via a special Signaling Cipher Suite Value (SCSV) 614 + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", with code point {0x00, 0xFF}. 615 + This SCSV is not a true cipher suite (it does not correspond to any 616 + valid set of algorithms) and cannot be negotiated. Instead, it has 617 + the same semantics as an empty "renegotiation_info" extension, as 618 + described in the following sections. Because SSLv3 and TLS 619 + implementations reliably ignore unknown cipher suites, the SCSV may 620 + be safely sent to any server. *) 621 + | (_, `TLS_1_0) -> ([Packet.TLS_EMPTY_RENEGOTIATION_INFO_SCSV], []) 622 + | (`TLS_1_3, _) -> ([], []) 623 + | _ -> ([], [`SecureRenegotiation ""]) 624 + in 625 + 626 + let client_hello = 627 + { dch with 628 + ciphersuites = dch.ciphersuites @ ciphers ; 629 + extensions = dch.extensions @ extensions } 630 + in 631 + 632 + let client_hello, ch, raw = 633 + match config.Config.cached_ticket, config.Config.ticket_cache with 634 + | None, _ | _, None -> 635 + let ch = ClientHello client_hello in 636 + client_hello, ch, Writer.assemble_handshake ch 637 + | Some (psk, epoch), Some cache -> 638 + let kex = `PskKeyExchangeModes [ Packet.PSK_KE_DHE ] in 639 + (* what next!? *) 640 + let now = cache.Config.timestamp () in 641 + (* TODO check lifetime! *) 642 + let obf_age = 643 + let span = Ptime.Span.to_float_s (Ptime.diff now psk.issued_at) in 644 + (* _in milliseconds_ *) 645 + let ms = int_of_float (span *. 1000.) in 646 + Int32.add psk.obfuscation (Int32.of_int ms) 647 + in 648 + let cipher = match Ciphersuite.ciphersuite_to_ciphersuite13 epoch.ciphersuite with 649 + | None -> assert false 650 + | Some c -> c 651 + in 652 + (* if all goes well, we can compute the binder key and embed into ch! *) 653 + let early_secret = Handshake_crypto13.(derive (empty cipher) psk.secret) in 654 + let binder_key = Handshake_crypto13.derive_secret early_secret "res binder" "" in 655 + 656 + let hash = 657 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 cipher)) in 658 + String.make H.digest_size '\x00' 659 + in 660 + let incomplete_psks = [ (psk.identifier, obf_age), hash ] in 661 + let ch' = { client_hello with extensions = client_hello.extensions @ [ kex ; `PreSharedKeys incomplete_psks ] } in 662 + let ch'_raw = Writer.assemble_handshake (ClientHello ch') in 663 + 664 + let binders_len = binders_len incomplete_psks in 665 + let ch_part = String.(sub ch'_raw 0 (length ch'_raw - binders_len)) in 666 + let binder = Handshake_crypto13.finished early_secret.hash binder_key ch_part in 667 + let blen = String.length binder in 668 + let prefix = Bytes.create 3 in 669 + Bytes.set_uint16_be prefix 0 (blen + 1) ; 670 + Bytes.set_uint8 prefix 2 blen ; 671 + let raw = String.concat "" [ ch_part ; Bytes.unsafe_to_string prefix ; binder ] in 672 + 673 + let psks = [(psk.identifier, obf_age), binder] in 674 + let client_hello' = { client_hello with extensions = client_hello.extensions @ [ kex ; `PreSharedKeys psks ] } in 675 + let ch' = ClientHello client_hello' in 676 + client_hello', ch', raw 677 + in 678 + 679 + let machina = AwaitServerHello (client_hello, secrets, [raw]) in 680 + 681 + (* from RFC5246, appendix E.1 682 + TLS clients that wish to negotiate with older servers MAY send any 683 + value {03,XX} as the record layer version number. Typical values 684 + would be {03,00}, the lowest version number supported by the client, 685 + and the value of ClientHello.client_version. No single value will 686 + guarantee interoperability with all old servers, but this is a 687 + complex topic beyond the scope of this document. *) 688 + let version = min_protocol_version Config.(config.protocol_versions) in 689 + let handshake = { 690 + state.handshake with 691 + machina = Client machina ; 692 + protocol_version = version 693 + } in 694 + let state = { state with handshake } in 695 + 696 + Tracing.hs ~tag:"handshake-out" ch ; 697 + send_records state [(Packet.HANDSHAKE, raw)] 698 + 699 + let server config = new_state Config.(of_server config) `Server 700 + 701 + let epoch state = 702 + Option.to_result ~none:() (epoch_of_hs state.handshake) 703 + 704 + let export_key_material (e : epoch_data) ?context label length = 705 + match e.protocol_version with 706 + | `TLS_1_3 -> 707 + let hash = 708 + let cipher = Option.get (Ciphersuite.ciphersuite_to_ciphersuite13 e.ciphersuite) in 709 + Ciphersuite.hash13 cipher 710 + in 711 + let module H = (val Digestif.module_of_hash' hash) in 712 + let ems = e.exporter_master_secret in 713 + let prk = 714 + let ctx = H.(to_raw_string (digest_string "")) in 715 + Handshake_crypto13.derive_secret_no_hash hash ems ~ctx label 716 + in 717 + let ctx = Option.value ~default:"" context in 718 + Handshake_crypto13.derive_secret_no_hash 719 + hash prk ~ctx:H.(to_raw_string (digest_string ctx)) 720 + ~length "exporter" 721 + | #tls_before_13 as v -> 722 + let seed = 723 + let base = 724 + match e.side with 725 + | `Server -> e.peer_random ^ e.own_random 726 + | `Client -> e.own_random ^ e.peer_random 727 + in 728 + match context with 729 + | None -> base 730 + | Some data -> 731 + let len = Bytes.create 2 in 732 + Bytes.set_uint16_be len 0 (String.length data); 733 + String.concat "" [ base ; Bytes.unsafe_to_string len ; data ] 734 + in 735 + Handshake_crypto.pseudo_random_function v e.ciphersuite 736 + length e.master_secret label seed 737 + 738 + let channel_binding e = function 739 + | `Tls_exporter -> 740 + Ok (export_key_material e "EXPORTER-Channel-Binding" 32) 741 + | `Tls_server_endpoint -> 742 + let ( let* ) = Result.bind in 743 + let* cert = 744 + match e.side, e.peer_certificate, e.own_certificate with 745 + | `Client, Some cert, _ -> Ok cert 746 + | `Server, _, cert :: _ -> Ok cert 747 + | `Client, _, _ -> Error (`Msg "no certificate received from the server") 748 + | `Server, _, _ -> Error (`Msg "certificate not available") 749 + in 750 + let* sigalg = 751 + Option.to_result ~none:(`Msg "unknown signature algorithm in certificate") 752 + (Option.map snd (X509.Certificate.signature_algorithm cert)) 753 + in 754 + let hash = match sigalg with `MD5 | `SHA1 -> `SHA256 | x -> x in 755 + Ok (X509.Certificate.fingerprint hash cert) 756 + | `Tls_unique -> 757 + match e.protocol_version, e.tls_unique with 758 + | `TLS_1_3, _ -> 759 + Error (`Msg "tls-unique not defined for TLS 1.3") 760 + | _, None -> Error (`Msg "couldn't find a tls-unique in the session data") 761 + | _, Some data -> Ok data
+172
vendor/opam/tls/lib/engine.mli
··· 1 + (** Transport layer security 2 + 3 + [TLS] is an implementation of 4 + {{:https://en.wikipedia.org/wiki/Transport_Layer_Security}transport 5 + layer security} in OCaml. TLS is a widely used security protocol 6 + which establishes an end-to-end secure channel (with optional 7 + (mutual) authentication) between two endpoints. It uses TCP/IP as 8 + transport. This library supports all four versions of TLS: 9 + {{:https://tools.ietf.org/html/rfc8446}1.3, RFC8446}, 10 + {{:https://tools.ietf.org/html/rfc5246}1.2, RFC5246}, 11 + {{:https://tools.ietf.org/html/rfc4346}1.1, RFC4346}, and 12 + {{:https://tools.ietf.org/html/rfc2246}1.0, RFC2246}. SSL, the 13 + previous protocol definition, is not supported. 14 + 15 + TLS is algorithmically agile: protocol version, key exchange 16 + algorithm, symmetric cipher, and message authentication code are 17 + negotiated upon connection. 18 + 19 + This library implements several extensions of TLS, 20 + {{:https://tools.ietf.org/html/rfc3268}AES ciphers}, 21 + {{:https://tools.ietf.org/html/rfc4366}TLS extensions} (such as 22 + server name indication, SNI), 23 + {{:https://tools.ietf.org/html/rfc5746}Renegotiation extension}, 24 + {{:https://tools.ietf.org/html/rfc7627}Session Hash and Extended 25 + Master Secret Extension}. 26 + 27 + This library does not contain insecure cipher suites (such as 28 + single DES, export ciphers, ...). It does not expose the server 29 + time in the server random, requires secure renegotiation. 30 + 31 + This library consists of a core, implemented in a purely 32 + functional matter ({!Engine}, this module), and effectful parts: 33 + {!Tls_lwt} and {!Tls_mirage}. 34 + 35 + {e %%VERSION%%} *) 36 + 37 + 38 + (** {1 Abstract state type} *) 39 + 40 + (** The abstract type of a TLS state. *) 41 + type state 42 + 43 + (** {1 Constructors} *) 44 + 45 + (** [client client] is [tls * out] where [tls] is the initial state, 46 + and [out] the initial client hello *) 47 + val client : Config.client -> (state * string) 48 + 49 + (** [server server] is [tls] where [tls] is the initial server 50 + state *) 51 + val server : Config.server -> state 52 + 53 + (** {1 Protocol failures} *) 54 + 55 + (** failures which can be mitigated by reconfiguration *) 56 + type error = [ 57 + | `AuthenticationFailure of X509.Validation.validation_error 58 + | `NoConfiguredCiphersuite of Ciphersuite.ciphersuite list 59 + | `NoConfiguredVersions of Core.tls_version list 60 + | `NoConfiguredSignatureAlgorithm of Core.signature_algorithm list 61 + | `NoMatchingCertificateFound of string 62 + | `CouldntSelectCertificate 63 + ] 64 + 65 + (** failures from received garbage or lack of features *) 66 + type fatal = [ 67 + | `Protocol_version of [ 68 + | `None_supported of Core.tls_any_version list 69 + | `Unknown_record of int * int 70 + | `Bad_record of Core.tls_any_version 71 + ] 72 + | `Unexpected of [ 73 + | `Content_type of int 74 + | `Message of string 75 + | `Handshake of Core.tls_handshake 76 + ] 77 + | `Decode of string 78 + | `Handshake of [ 79 + | `Message of string 80 + | `Fragments 81 + | `BadDH of string 82 + | `BadECDH of Mirage_crypto_ec.error 83 + ] 84 + | `Bad_certificate of string 85 + | `Missing_extension of string 86 + | `Bad_mac 87 + | `Record_overflow of int 88 + | `Unsupported_extension 89 + | `Inappropriate_fallback 90 + | `No_application_protocol 91 + ] 92 + 93 + (** type of failures *) 94 + type failure = [ 95 + | `Error of error 96 + | `Fatal of fatal 97 + | `Alert of Packet.alert_type 98 + ] 99 + 100 + (** [alert_of_failure failure] is [alert], the TLS alert type for this failure. *) 101 + val alert_of_failure : failure -> Packet.alert_level * Packet.alert_type 102 + 103 + (** [string_of_failure failure] is [string], the string representation of the [failure]. *) 104 + val string_of_failure : failure -> string 105 + 106 + (** [pp_failure failure] pretty-prints failure. *) 107 + val pp_failure : failure Fmt.t 108 + 109 + (** {1 Protocol handling} *) 110 + 111 + (** result type of {!handle_tls}: either failed to handle the incoming 112 + buffer ([`Fail]) with {!failure} and potentially a message to send 113 + to the other endpoint, or sucessful operation ([`Ok]) with a new 114 + {!state}, an end of file ([`Eof]), or an incoming ([`Alert]). 115 + Possibly some [`Response] to the other endpoint is needed, and 116 + potentially some [`Data] for the application was received. *) 117 + type ret = 118 + (state * [ `Eof ] option 119 + * [ `Response of string option ] 120 + * [ `Data of string option ], 121 + failure * [ `Response of string ]) result 122 + 123 + (** [handle_tls state buffer] is [ret], depending on incoming [state] 124 + and [buffer], the result is the appropriate {!ret} *) 125 + val handle_tls : state -> string -> ret 126 + 127 + (** [handshake_in_progrss state] is a predicate which indicates whether there 128 + is a handshake in progress or scheduled. *) 129 + val handshake_in_progress : state -> bool 130 + 131 + (** [send_application_data tls outs] is [Some (tls', out)] where 132 + [tls'] is the new tls state, and [out] the cstruct to send over the 133 + wire (encrypted [outs]) when the TLS session is ready. When the TLS 134 + session is not ready it is [None]. *) 135 + val send_application_data : state -> string list -> (state * string) option 136 + 137 + (** [send_close_notify tls] is [tls' * out] where [tls'] is the new 138 + tls state, and out the (possible encrypted) close notify alert. *) 139 + val send_close_notify : state -> state * string 140 + 141 + (** [reneg ~authenticator ~acceptable_cas ~cert tls] initiates a renegotation on 142 + [tls], using the provided [authenticator]. It is [tls' * out] where [tls'] 143 + is the new tls state, and [out] either a client hello or hello request 144 + (depending on which communication endpoint [tls] is). *) 145 + val reneg : ?authenticator:X509.Authenticator.t -> 146 + ?acceptable_cas:X509.Distinguished_name.t list -> ?cert:Config.own_cert -> 147 + state -> (state * string) option 148 + 149 + (** [key_update ~request state] initiates a KeyUpdate (TLS 1.3 only). If 150 + [request] is provided and [true] (the default), the KeyUpdate message 151 + contains a request that the peer should update their traffic key as well. *) 152 + val key_update : ?request:bool -> state -> (state * string, failure) result 153 + 154 + (** {1 Session information} *) 155 + 156 + (** [epoch state] is [epoch], which contains the session 157 + information. If there's no established session yet, an error is returned. *) 158 + val epoch : state -> (Core.epoch_data, unit) result 159 + 160 + (** [export_key_material epoch_data ?context label length] is the RFC 5705 161 + exported key material of [length] bytes using [label] and, if provided, 162 + [context]. *) 163 + val export_key_material : Core.epoch_data -> ?context:string -> string -> int -> 164 + string 165 + 166 + (** [channel_binding epoch_data mode] is the RFC 5929 and RFC 9266 specified 167 + channel binding. Please note that [`Tls_unique] will error for TLS 1.3 168 + sessions, and [`Tls_exporter] is not recommended for TLS < 1.3 sessions 169 + (unless the uniqueness is ensured via another path). *) 170 + val channel_binding : Core.epoch_data -> 171 + [ `Tls_exporter | `Tls_unique | `Tls_server_endpoint ] -> 172 + (string, [ `Msg of string ]) result
vendor/opam/tls/lib/explorator.ml

This is a binary file and will not be displayed.

+544
vendor/opam/tls/lib/handshake_client.ml
··· 1 + open Core 2 + open State 3 + open Handshake_common 4 + open Config 5 + 6 + let state_version state = match state.protocol_version with 7 + | #tls_before_13 as v -> v 8 + | _ -> assert false 9 + 10 + let default_client_hello config = 11 + let host = match config.peer_name with 12 + | None -> [] 13 + | Some x -> [`Hostname x] 14 + in 15 + let version = max_protocol_version config.protocol_versions in 16 + let ecc_groups = match List.filter Config.elliptic_curve config.groups with 17 + | [] -> [] 18 + | xs -> [ `ECPointFormats ; `SupportedGroups (List.map group_to_named_group xs) ] 19 + in 20 + let extensions, secrets = match version with 21 + | `TLS_1_0 | `TLS_1_1 -> (ecc_groups, []) 22 + | `TLS_1_2 -> 23 + (`SignatureAlgorithms config.signature_algorithms :: ecc_groups, []) 24 + | `TLS_1_3 -> 25 + let sig_alg = config.signature_algorithms (* TODO: filter deprecated ones *) 26 + and groups = List.map group_to_named_group config.groups 27 + and secrets, keyshares = 28 + (* OTOH, we could send all the keyshares (but this is pretty substantial size) *) 29 + (* instead we pick the first two groups and send keyshares *) 30 + let rec gen c gs acc = match c with 31 + | 0 -> List.rev acc 32 + | _ -> match gs with 33 + | [] -> List.rev acc (* TODO log? complain? *) 34 + | g::gs' -> 35 + let priv, share = Handshake_crypto13.dh_gen_key g in 36 + let acc' = ((g, priv),(group_to_named_group g, share)) :: acc in 37 + gen (pred c) gs' acc' 38 + in 39 + List.split (gen 2 config.groups []) 40 + in 41 + let all = all_versions config.protocol_versions in 42 + let supported_versions = List.map (fun x -> (x :> tls_any_version)) all in 43 + let point_format = 44 + if min_protocol_version config.protocol_versions = `TLS_1_3 then 45 + [] 46 + else 47 + [ `ECPointFormats ] 48 + in 49 + let exts = 50 + point_format @ [`SignatureAlgorithms sig_alg ; `SupportedGroups groups ; `KeyShare keyshares ; `SupportedVersions supported_versions ] 51 + in 52 + (exts, secrets) 53 + in 54 + let alpn = match config.alpn_protocols with 55 + | [] -> [] 56 + | protocols -> [`ALPN protocols] 57 + in 58 + let sessionid = 59 + match config.use_reneg, config.cached_session with 60 + | _, Some { session_id ; extended_ms ; _ } when extended_ms && not (String.length session_id = 0) -> Some session_id 61 + | false, Some { session_id ; _ } when not (String.length session_id = 0) -> Some session_id 62 + | _ -> None 63 + in 64 + let ch = { 65 + client_version = (version :> tls_any_version) ; 66 + client_random = Mirage_crypto_rng.generate 32 ; 67 + sessionid = sessionid ; 68 + ciphersuites = List.map Ciphersuite.ciphersuite_to_any_ciphersuite config.ciphers ; 69 + extensions = `ExtendedMasterSecret :: host @ extensions @ alpn 70 + } 71 + in 72 + (ch, version, secrets) 73 + 74 + let common_server_hello_validation config reneg (sh : server_hello) (ch : client_hello) = 75 + let validate_reneg data = 76 + let err = `Fatal (`Handshake (`Message "invalid renegotiation")) in 77 + match reneg, data with 78 + | Some (cvd, svd), Some x -> guard (String.equal (cvd ^ svd) x) err 79 + | Some _, None -> Error err 80 + | None, Some x -> guard (String.length x = 0) err 81 + | None, None -> Ok () 82 + in 83 + let* () = 84 + guard (List.mem sh.ciphersuite config.ciphers) 85 + (`Error (`NoConfiguredCiphersuite [sh.ciphersuite])) 86 + in 87 + let* () = 88 + guard (server_hello_valid sh && 89 + server_exts_subset_of_client sh.extensions ch.extensions) 90 + (`Fatal `Unsupported_extension) 91 + in 92 + let* () = 93 + match get_alpn_protocol sh with 94 + | None -> Ok () 95 + | Some x -> 96 + guard (List.mem x config.alpn_protocols) (`Fatal `Unsupported_extension) 97 + in 98 + validate_reneg (get_secure_renegotiation sh.extensions) 99 + 100 + let common_server_hello_machina state (sh : server_hello) (ch : client_hello) raw log = 101 + let cipher = sh.ciphersuite in 102 + let session_id = Option.value ~default:"" sh.sessionid in 103 + let extended_ms = 104 + List.mem `ExtendedMasterSecret ch.extensions && 105 + List.mem `ExtendedMasterSecret sh.extensions 106 + in 107 + let alpn_protocol = get_alpn_protocol sh in 108 + let session = 109 + let session = empty_session in 110 + let common_session_data = { 111 + session.common_session_data with 112 + client_random = ch.client_random ; 113 + server_random = sh.server_random ; 114 + alpn_protocol ; 115 + } in { 116 + session with 117 + common_session_data ; 118 + ciphersuite = cipher ; 119 + session_id ; 120 + extended_ms ; 121 + client_version = ch.client_version ; 122 + } 123 + in 124 + let state = { state with protocol_version = sh.server_version } in 125 + match Ciphersuite.ciphersuite_kex cipher with 126 + | #Ciphersuite.key_exchange_algorithm_dhe -> 127 + let machina = Client (AwaitCertificate_DHE (session, log @ [raw])) in 128 + Ok ({ state with machina }, []) 129 + | `RSA -> 130 + let machina = Client (AwaitCertificate_RSA (session, log @ [raw])) in 131 + Ok ({ state with machina }, []) 132 + 133 + let answer_server_hello state (ch : client_hello) sh secrets raw log = 134 + let validate_version requested (lo, _) server_version = 135 + guard (version_ge requested server_version && server_version >= lo) 136 + (`Error (`NoConfiguredVersions [ server_version ])) 137 + in 138 + 139 + let cfg = state.config in 140 + let* () = common_server_hello_validation cfg None sh ch in 141 + let* () = validate_version ch.client_version state.config.protocol_versions sh.server_version in 142 + 143 + let* () = 144 + if max_protocol_version state.config.protocol_versions = `TLS_1_3 then 145 + let* () = 146 + guard (not (Utils.sub_equal ~off:24 ~len:8 Packet.downgrade12 sh.server_random)) 147 + (`Fatal (`Handshake (`Message "random contains downgrade TLS 1.2"))) 148 + in 149 + guard (not (Utils.sub_equal ~off:24 ~len:8 Packet.downgrade11 sh.server_random)) 150 + (`Fatal (`Handshake (`Message "random contains downgrade TLS 1.1"))) 151 + else 152 + Ok () 153 + in 154 + 155 + let epoch_matches (epoch : epoch_data) = 156 + epoch.ciphersuite = sh.ciphersuite && 157 + epoch.protocol_version = sh.server_version && 158 + Option.fold ~none:false ~some:(SessionID.equal epoch.session_id) sh.sessionid && 159 + (not cfg.use_reneg || 160 + (List.mem `ExtendedMasterSecret sh.extensions && epoch.extended_ms)) 161 + in 162 + 163 + Tracing.debug (fun m -> m "version %a" pp_tls_version sh.server_version) ; 164 + trace_cipher sh.ciphersuite ; 165 + 166 + let state = { state with protocol_version = sh.server_version } in 167 + match sh.server_version with 168 + | #tls13 -> 169 + Handshake_client13.answer_server_hello state ch sh secrets raw (String.concat "" log) 170 + | #tls_before_13 as v -> 171 + match state.config.cached_session with 172 + | Some epoch when epoch_matches epoch -> 173 + let session = 174 + let session = session_of_epoch epoch in 175 + let common_session_data = { 176 + session.common_session_data with 177 + client_random = ch.client_random ; 178 + server_random = sh.server_random ; 179 + client_auth = match epoch.own_certificate with [] -> false | _ -> true ; 180 + } in 181 + { session with 182 + common_session_data ; 183 + client_version = ch.client_version ; 184 + } 185 + in 186 + let client_ctx, server_ctx = 187 + Handshake_crypto.initialise_crypto_ctx v session 188 + in 189 + let machina = AwaitServerChangeCipherSpecResume (session, client_ctx, server_ctx, log @ [raw]) in 190 + Ok ({ state with machina = Client machina }, []) 191 + | _ -> common_server_hello_machina state sh ch raw log 192 + 193 + let answer_server_hello_renegotiate state session (ch : client_hello) sh raw log = 194 + let* () = common_server_hello_validation state.config (Some session.renegotiation) sh ch in 195 + let* () = 196 + guard (state.protocol_version = sh.server_version) 197 + (`Fatal (`Handshake (`Message "invalid renegotiation version"))) 198 + in 199 + common_server_hello_machina state sh ch raw log 200 + 201 + let validate_keyusage certificate kex = 202 + let usage = Ciphersuite.required_usage kex in 203 + let* cert = 204 + Option.to_result ~none:(`Fatal (`Bad_certificate "none received")) certificate 205 + in 206 + let* () = 207 + guard (supports_key_usage ~not_present:true usage cert) 208 + (`Fatal (`Bad_certificate "key usage")) 209 + in 210 + guard 211 + (supports_extended_key_usage `Server_auth cert || 212 + supports_extended_key_usage ~not_present:true `Any cert) 213 + (`Fatal (`Bad_certificate "extended key usage")) 214 + 215 + let answer_certificate_RSA state (session : session_data) cs raw log = 216 + let cfg = state.config in 217 + let* peer_certificate, received_certificates, peer_certificate_chain, trust_anchor = 218 + validate_chain cfg.authenticator cs cfg.ip cfg.peer_name 219 + in 220 + let* () = validate_keyusage peer_certificate `RSA in 221 + let session = 222 + let common_session_data = { session.common_session_data with received_certificates ; peer_certificate ; peer_certificate_chain ; trust_anchor } in 223 + { session with common_session_data } 224 + in 225 + let* version = 226 + match session.client_version with 227 + | `TLS_1_3 -> Ok `TLS_1_2 228 + | #tls_before_13 as v -> Ok v 229 + | _ -> assert false 230 + in 231 + let buf = Bytes.create (2 + 46) in 232 + let _ver = Writer.assemble_protocol_version ~buf version in 233 + Mirage_crypto_rng.generate_into buf ~off:2 46; 234 + let premaster = Bytes.unsafe_to_string buf in 235 + let* k = peer_key peer_certificate in 236 + match k with 237 + | `RSA key -> 238 + let kex = Mirage_crypto_pk.Rsa.PKCS1.encrypt ~key premaster in 239 + let kex = Writer.assemble_client_dh_key_exchange kex in 240 + let machina = 241 + AwaitCertificateRequestOrServerHelloDone 242 + (session, kex, premaster, log @ [raw]) 243 + in 244 + Ok ({ state with machina = Client machina }, []) 245 + | _ -> Error (`Fatal (`Bad_certificate "not an RSA certificate")) 246 + 247 + let answer_certificate_DHE state (session : session_data) cs raw log = 248 + let cfg = state.config in 249 + let* peer_certificate, received_certificates, peer_certificate_chain, trust_anchor = 250 + validate_chain cfg.authenticator cs cfg.ip cfg.peer_name 251 + in 252 + let* () = validate_keyusage peer_certificate `FFDHE in 253 + let session = 254 + let common_session_data = { session.common_session_data with received_certificates ; peer_certificate ; peer_certificate_chain ; trust_anchor } in 255 + { session with common_session_data } 256 + in 257 + let machina = AwaitServerKeyExchange_DHE (session, log @ [raw]) in 258 + Ok ({ state with machina = Client machina }, []) 259 + 260 + let answer_server_key_exchange_DHE state (session : session_data) kex raw log = 261 + let* group, shared, raw_dh_params, leftover = 262 + if Ciphersuite.ecdhe session.ciphersuite then 263 + let* g, share, raw, left = 264 + map_reader_error (Reader.parse_ec_parameters kex) 265 + in 266 + Ok (`Ec g, share, raw, left) 267 + else 268 + let unpack_dh dh_params = 269 + Result.map_error 270 + (function `Msg m -> `Fatal (`Decode m)) 271 + (Crypto.dh_params_unpack dh_params) 272 + in 273 + let* dh_params, raw_dh_params, leftover = 274 + map_reader_error (Reader.parse_dh_parameters kex) 275 + in 276 + let* group, shared = unpack_dh dh_params in 277 + let* () = 278 + guard (Mirage_crypto_pk.Dh.modulus_size group >= Config.min_dh_size) 279 + (`Fatal (`Handshake (`BadDH "too small"))) 280 + in 281 + Ok (`Finite_field group, shared, raw_dh_params, leftover) 282 + in 283 + 284 + let sigdata = 285 + String.concat "" [ 286 + session.common_session_data.client_random ; 287 + session.common_session_data.server_random ; 288 + raw_dh_params 289 + ] 290 + in 291 + let* () = 292 + verify_digitally_signed state.protocol_version 293 + state.config.signature_algorithms leftover sigdata 294 + session.common_session_data.peer_certificate 295 + in 296 + 297 + let* pms, kex = 298 + let open Mirage_crypto_ec in 299 + let map_ecdh_error = 300 + Result.map_error (fun e -> `Fatal (`Handshake (`BadECDH e))) 301 + in 302 + match group with 303 + | `Finite_field g -> 304 + let secret, client_share = Mirage_crypto_pk.Dh.gen_key g in 305 + let* pms = 306 + Option.to_result 307 + ~none:(`Fatal (`Handshake (`BadDH "invalid FF"))) 308 + (Mirage_crypto_pk.Dh.shared secret shared) 309 + in 310 + Ok (pms, Writer.assemble_client_dh_key_exchange client_share) 311 + | `Ec `P256 -> 312 + let secret, client_share = P256.Dh.gen_key () in 313 + let* pms = map_ecdh_error (P256.Dh.key_exchange secret shared) in 314 + Ok (pms, Writer.assemble_client_ec_key_exchange client_share) 315 + | `Ec `P384 -> 316 + let secret, client_share = P384.Dh.gen_key () in 317 + let* pms = map_ecdh_error (P384.Dh.key_exchange secret shared) in 318 + Ok (pms, Writer.assemble_client_ec_key_exchange client_share) 319 + | `Ec `P521 -> 320 + let secret, client_share = P521.Dh.gen_key () in 321 + let* pms = map_ecdh_error (P521.Dh.key_exchange secret shared) in 322 + Ok (pms, Writer.assemble_client_ec_key_exchange client_share) 323 + | `Ec `X25519 -> 324 + let secret, client_share = X25519.gen_key () in 325 + let* pms = map_ecdh_error (X25519.key_exchange secret shared) in 326 + Ok (pms, Writer.assemble_client_ec_key_exchange client_share) 327 + in 328 + let machina = 329 + AwaitCertificateRequestOrServerHelloDone 330 + (session, kex, pms, log @ [raw]) 331 + in 332 + Ok ({ state with machina = Client machina }, []) 333 + 334 + let answer_certificate_request state (session : session_data) cr kex pms raw log = 335 + let cfg = state.config in 336 + let* _types, sigalgs, _cas = 337 + match state_version state with 338 + | `TLS_1_0 | `TLS_1_1 -> 339 + let* types, cas = 340 + map_reader_error (Reader.parse_certificate_request cr) 341 + in 342 + Ok (types, None, cas) 343 + | `TLS_1_2 -> 344 + let* types, sigalgs, cas = 345 + map_reader_error (Reader.parse_certificate_request_1_2 cr) 346 + in 347 + Ok (types, Some sigalgs, cas) 348 + in 349 + (* TODO: respect _types and _cas, multiple client certificates *) 350 + let own_certificate, own_private_key = 351 + match cfg.own_certificates with 352 + | `Single (chain, priv) -> (chain, Some priv) 353 + | _ -> ([], None) 354 + in 355 + let session = 356 + let common_session_data = { 357 + session.common_session_data with 358 + own_certificate ; 359 + own_private_key ; 360 + client_auth = true 361 + } in 362 + { session with common_session_data } 363 + in 364 + let machina = AwaitServerHelloDone (session, sigalgs, kex, pms, log @ [raw]) in 365 + Ok ({ state with machina = Client machina }, []) 366 + 367 + let answer_server_hello_done state (session : session_data) sigalgs kex premaster raw log = 368 + let kex = ClientKeyExchange kex in 369 + let ckex = Writer.assemble_handshake kex in 370 + 371 + let* msgs, raw_msgs, raws, cert_verify = 372 + match session.common_session_data.client_auth, session.common_session_data.own_private_key with 373 + | true, Some p -> 374 + let cs = List.map X509.Certificate.encode_der session.common_session_data.own_certificate in 375 + let cert = Certificate (Writer.assemble_certificates cs) in 376 + let ccert = Writer.assemble_handshake cert in 377 + let to_sign = log @ [ raw ; ccert ; ckex ] in 378 + let data = String.concat "" to_sign in 379 + let ver = state.protocol_version 380 + and my_sigalgs = state.config.signature_algorithms in 381 + let* signature = signature ver data sigalgs my_sigalgs p in 382 + let cert_verify = CertificateVerify signature in 383 + let ccert_verify = Writer.assemble_handshake cert_verify in 384 + Ok ([ cert ; kex ; cert_verify ], 385 + [ ccert ; ckex ; ccert_verify ], 386 + to_sign, Some ccert_verify) 387 + | true, None -> 388 + let cert = Certificate (Writer.assemble_certificates []) in 389 + let ccert = Writer.assemble_handshake cert in 390 + Ok ([cert ; kex], [ccert ; ckex], log @ [ raw ; ccert ; ckex ], None) 391 + | false, _ -> 392 + Ok ([kex], [ckex], log @ [ raw ; ckex ], None) 393 + in 394 + 395 + let to_fin = raws @ Option.to_list cert_verify in 396 + 397 + let master_secret = 398 + Handshake_crypto.derive_master_secret (state_version state) session premaster raws 399 + in 400 + let session = 401 + let common_session_data = { session.common_session_data with master_secret } in 402 + { session with common_session_data } 403 + in 404 + let client_ctx, server_ctx = 405 + Handshake_crypto.initialise_crypto_ctx (state_version state) session 406 + in 407 + 408 + let checksum = Handshake_crypto.finished (state_version state) session.ciphersuite master_secret "client finished" to_fin in 409 + let fin = Finished checksum in 410 + let raw_fin = Writer.assemble_handshake fin in 411 + let session = { session with tls_unique = checksum } in 412 + let ps = to_fin @ [raw_fin] in 413 + 414 + let session = 415 + let common_session_data = { session.common_session_data with master_secret } in 416 + { session with common_session_data } 417 + in 418 + let machina = AwaitServerChangeCipherSpec (session, server_ctx, checksum, ps) 419 + and ccst, ccs = change_cipher_spec in 420 + 421 + List.iter (Tracing.hs ~tag:"handshake-out") msgs; 422 + Tracing.cs ~tag:"change-cipher-spec-out" ccs ; 423 + Tracing.cs ~tag:"master-secret" master_secret; 424 + Tracing.hs ~tag:"handshake-out" fin; 425 + 426 + Ok ({ state with machina = Client machina }, 427 + List.map (fun x -> `Record (Packet.HANDSHAKE, x)) raw_msgs @ 428 + [ `Record (ccst, ccs); 429 + `Change_enc client_ctx; 430 + `Record (Packet.HANDSHAKE, raw_fin)]) 431 + 432 + let answer_server_finished state (session : session_data) client_verify fin log = 433 + let computed = 434 + Handshake_crypto.finished (state_version state) session.ciphersuite session.common_session_data.master_secret "server finished" log 435 + in 436 + let* () = 437 + guard (String.equal computed fin) 438 + (`Fatal (`Handshake (`Message "couldn't verify finished"))) 439 + in 440 + let* () = 441 + guard (String.length state.hs_fragment = 0) (`Fatal (`Handshake `Fragments)) 442 + in 443 + let machina = Established 444 + and session = { session with renegotiation = (client_verify, computed) } in 445 + Ok ({ state with machina = Client machina ; session = `TLS session :: state.session }, []) 446 + 447 + let answer_server_finished_resume state (session : session_data) fin raw log = 448 + let client, server = 449 + let checksum = Handshake_crypto.finished (state_version state) session.ciphersuite session.common_session_data.master_secret in 450 + (checksum "client finished" (log @ [raw]), checksum "server finished" log) 451 + in 452 + let* () = 453 + guard (String.equal server fin) 454 + (`Fatal (`Handshake (`Message "couldn't verify finished"))) 455 + in 456 + let session = { session with tls_unique = server } in 457 + let* () = 458 + guard (String.length state.hs_fragment = 0) 459 + (`Fatal (`Handshake `Fragments)) 460 + in 461 + let machina = Established 462 + and session = { session with renegotiation = (client, server) } 463 + in 464 + let finished = Finished client in 465 + let raw_finished = Writer.assemble_handshake finished in 466 + Tracing.hs ~tag:"handshake-out" finished ; 467 + Ok ({ state with machina = Client machina ; session = `TLS session :: state.session }, 468 + [`Record (Packet.HANDSHAKE, raw_finished)]) 469 + 470 + let answer_hello_request state = 471 + let produce_client_hello session config exts = 472 + let dch, _, _ = default_client_hello config in 473 + let ch = { dch with extensions = dch.extensions @ exts ; sessionid = None } in 474 + let raw = Writer.assemble_handshake (ClientHello ch) in 475 + let machina = AwaitServerHelloRenegotiate (session, ch, [raw]) in 476 + Tracing.hs ~tag:"handshake-out" (ClientHello ch) ; 477 + ({ state with machina = Client machina }, [`Record (Packet.HANDSHAKE, raw)]) 478 + in 479 + 480 + match state.config.use_reneg, state.session with 481 + | true , `TLS x :: _ -> 482 + let ext = `SecureRenegotiation (fst x.renegotiation) in 483 + Ok (produce_client_hello x state.config [ext]) 484 + | true , _ -> Error (`Fatal (`Handshake (`Message "couldn't find session"))) 485 + | false, _ -> 486 + let no_reneg = Writer.assemble_alert ~level:Packet.WARNING Packet.NO_RENEGOTIATION in 487 + Tracing.debug (fun m -> m "alert-out (warning, no_renegotiation)") ; 488 + Ok (state, [`Record (Packet.ALERT, no_reneg)]) 489 + 490 + let handle_change_cipher_spec cs state packet = 491 + let* () = map_reader_error (Reader.parse_change_cipher_spec packet) in 492 + match cs with 493 + | AwaitServerChangeCipherSpec (session, server_ctx, client_verify, log) -> 494 + let* () = 495 + guard (String.length state.hs_fragment = 0) 496 + (`Fatal (`Handshake `Fragments)) 497 + in 498 + let machina = AwaitServerFinished (session, client_verify, log) in 499 + Tracing.cs ~tag:"change-cipher-spec-in" packet ; 500 + Ok ({ state with machina = Client machina }, [`Change_dec server_ctx]) 501 + | AwaitServerChangeCipherSpecResume (session, client_ctx, server_ctx, log) -> 502 + let* () = 503 + guard (String.length state.hs_fragment = 0) 504 + (`Fatal (`Handshake `Fragments)) 505 + in 506 + let ccs = change_cipher_spec in 507 + let machina = AwaitServerFinishedResume (session, log) in 508 + Tracing.cs ~tag:"change-cipher-spec-in" packet ; 509 + Tracing.cs ~tag:"change-cipher-spec-out" packet ; 510 + Ok ({ state with machina = Client machina }, 511 + [`Record ccs ; `Change_enc client_ctx; `Change_dec server_ctx]) 512 + | _ -> Error (`Fatal (`Unexpected (`Message "change cipher spec"))) 513 + 514 + let handle_handshake cs hs buf = 515 + let* handshake = map_reader_error (Reader.parse_handshake buf) in 516 + Tracing.hs ~tag:"handshake-in" handshake ; 517 + match cs, handshake with 518 + | AwaitServerHello (ch, secrets, log), ServerHello sh -> 519 + answer_server_hello hs ch sh secrets buf log 520 + | AwaitServerHello (ch, secrets, log), HelloRetryRequest hrr -> 521 + Handshake_client13.answer_hello_retry_request hs ch hrr secrets buf (String.concat "" log) 522 + | AwaitServerHelloRenegotiate (session, ch, log), ServerHello sh -> 523 + answer_server_hello_renegotiate hs session ch sh buf log 524 + | AwaitCertificate_RSA (session, log), Certificate cs -> 525 + let* cs = map_reader_error (Reader.parse_certificates cs) in 526 + answer_certificate_RSA hs session cs buf log 527 + | AwaitCertificate_DHE (session, log), Certificate cs -> 528 + let* cs = map_reader_error (Reader.parse_certificates cs) in 529 + answer_certificate_DHE hs session cs buf log 530 + | AwaitServerKeyExchange_DHE (session, log), ServerKeyExchange kex -> 531 + answer_server_key_exchange_DHE hs session kex buf log 532 + | AwaitCertificateRequestOrServerHelloDone (session, kex, pms, log), CertificateRequest cr -> 533 + answer_certificate_request hs session cr kex pms buf log 534 + | AwaitCertificateRequestOrServerHelloDone (session, kex, pms, log), ServerHelloDone -> 535 + answer_server_hello_done hs session None kex pms buf log 536 + | AwaitServerHelloDone (session, sigalgs, kex, pms, log), ServerHelloDone -> 537 + answer_server_hello_done hs session sigalgs kex pms buf log 538 + | AwaitServerFinished (session, client_verify, log), Finished fin -> 539 + answer_server_finished hs session client_verify fin log 540 + | AwaitServerFinishedResume (session, log), Finished fin -> 541 + answer_server_finished_resume hs session fin buf log 542 + | Established, HelloRequest -> 543 + answer_hello_request hs 544 + | _, hs -> Error (`Fatal (`Unexpected (`Handshake hs)))
+7
vendor/opam/tls/lib/handshake_client.mli
··· 1 + open Core 2 + open State 3 + 4 + val default_client_hello : Config.config -> (client_hello * tls_version * (group * dh_secret) list) 5 + val handle_change_cipher_spec : client_handshake_state -> handshake_state -> string -> (handshake_return, failure) result 6 + val handle_handshake : client_handshake_state -> handshake_state -> string -> (handshake_return, failure) result 7 + val answer_hello_request : handshake_state -> (handshake_return, failure) result
+307
vendor/opam/tls/lib/handshake_client13.ml
··· 1 + open State 2 + open Core 3 + open Handshake_common 4 + open Config 5 + 6 + let answer_server_hello state ch (sh : server_hello) secrets raw log = 7 + (* assume SH valid, version 1.3, extensions are subset *) 8 + match Ciphersuite.ciphersuite_to_ciphersuite13 sh.ciphersuite with 9 + | None -> Error (`Fatal (`Handshake (`Message "not a TLS 1.3 ciphersuite"))) 10 + | Some cipher -> 11 + let* () = 12 + guard (List.mem cipher (ciphers13 state.config)) 13 + (`Fatal (`Handshake (`Message "not a configured ciphersuite"))) 14 + in 15 + let* () = guard (String.length state.hs_fragment = 0) (`Fatal (`Handshake `Fragments)) in 16 + 17 + (* TODO: PSK *) 18 + (* TODO: early_secret elsewhere *) 19 + match Utils.map_find ~f:(function `KeyShare ks -> Some ks | _ -> None) sh.extensions with 20 + | None -> Error (`Fatal (`Handshake (`Message "missing key share extension"))) 21 + | Some (g, share) -> 22 + match List.find_opt (fun (g', _) -> g = g') secrets with 23 + | None -> Error (`Fatal (`Handshake (`Message "couldn't find our secret for the key share"))) 24 + | Some (_, secret) -> 25 + let* shared = Handshake_crypto13.dh_shared secret share in 26 + let hlen = 27 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 cipher)) in 28 + H.digest_size 29 + in 30 + let* psk, resumed = 31 + match 32 + Utils.map_find ~f:(function `PreSharedKey idx -> Some idx | _ -> None) sh.extensions, 33 + state.config.Config.cached_ticket 34 + with 35 + | None, _ | _, None -> Ok (String.make hlen '\x00', false) 36 + | Some idx, Some (psk, _epoch) -> 37 + let* () = guard (idx = 0) (`Fatal (`Handshake (`Message "resumed pre-shared idx not 0"))) in 38 + Ok (psk.secret, true) 39 + in 40 + let early_secret = Handshake_crypto13.(derive (empty cipher) psk) in 41 + let hs_secret = Handshake_crypto13.derive early_secret shared in 42 + let log = log ^ raw in 43 + let server_hs_secret, server_ctx, client_hs_secret, client_ctx = 44 + Handshake_crypto13.hs_ctx hs_secret log in 45 + let master_secret = 46 + Handshake_crypto13.derive hs_secret (String.make hlen '\x00') 47 + in 48 + let session = 49 + let base = empty_session13 cipher in 50 + let common_session_data13 = 51 + { base.common_session_data13 with 52 + server_random = sh.server_random ; 53 + client_random = ch.client_random ; 54 + master_secret = master_secret.secret } 55 + in 56 + { base with master_secret ; common_session_data13 ; resumed } 57 + in 58 + let st = AwaitServerEncryptedExtensions13 (session, server_hs_secret, client_hs_secret, log) in 59 + Ok ({ state with machina = Client13 st ; protocol_version = `TLS_1_3 }, 60 + [ `Change_enc client_ctx ; `Change_dec server_ctx ]) 61 + 62 + (* called from handshake_client.ml *) 63 + let answer_hello_retry_request state (ch : client_hello) hrr _secrets raw log = 64 + (* when is a HRR invalid / what do we need to check? 65 + -> we advertised the group and cipher 66 + -> TODO we did advertise such a keyshare already (does it matter?) 67 + *) 68 + let* () = 69 + guard (`TLS_1_3 = hrr.retry_version) 70 + (`Fatal (`Handshake (`Message "hello retry request with a version <> 1.3"))) 71 + in 72 + let* () = 73 + guard (List.mem hrr.selected_group state.config.groups) 74 + (`Fatal (`Handshake (`Message "hello retry request with group we didn't advertise"))) 75 + in 76 + let* () = 77 + guard (List.mem hrr.ciphersuite (ciphers13 state.config)) 78 + (`Fatal (`Handshake (`Message "hello retet request with ciphersuite we didn't advertise"))) in 79 + (* generate a fresh keyshare *) 80 + let secret, keyshare = 81 + let g = hrr.selected_group in 82 + let priv, share = Handshake_crypto13.dh_gen_key g in 83 + (g, priv), (group_to_named_group g, share) 84 + in 85 + (* append server extensions (i.e. cookie!) *) 86 + let cookie = match Utils.map_find ~f:(function `Cookie c -> Some c | _ -> None) hrr.extensions with 87 + | None -> [] 88 + | Some c -> [ `Cookie c ] 89 + in 90 + (* use the same extensions as in original CH, apart from PSK!? and early_data *) 91 + let other_exts = List.filter (function `KeyShare _ -> false | _ -> true) ch.extensions in 92 + let new_ch = { ch with extensions = `KeyShare [keyshare] :: other_exts @ cookie} in 93 + let new_ch_raw = Writer.assemble_handshake (ClientHello new_ch) in 94 + let ch0_data = 95 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 hrr.ciphersuite)) in 96 + H.(to_raw_string (digest_string log)) 97 + in 98 + let ch0_hdr = Writer.assemble_message_hash (String.length ch0_data) in 99 + let st = AwaitServerHello13 (new_ch, [secret], String.concat "" [ ch0_hdr ; ch0_data ; raw ; new_ch_raw ]) in 100 + 101 + Tracing.hs ~tag:"handshake-out" (ClientHello new_ch); 102 + Ok ({ state with machina = Client13 st ; protocol_version = `TLS_1_3 }, [`Record (Packet.HANDSHAKE, new_ch_raw)]) 103 + 104 + let answer_encrypted_extensions state (session : session_data13) server_hs_secret client_hs_secret ee raw log = 105 + (* TODO we now know: - hostname - early_data (preserve this in session!!) *) 106 + (* next message is either CertificateRequest or Certificate (or finished if PSK) *) 107 + let alpn_protocol = Utils.map_find ~f:(function `ALPN proto -> Some proto | _ -> None) ee in 108 + let session = 109 + let common_session_data13 = { session.common_session_data13 with alpn_protocol } in 110 + { session with common_session_data13 } 111 + in 112 + let st = 113 + if session.resumed then 114 + AwaitServerFinished13 (session, server_hs_secret, client_hs_secret, None, log ^ raw) 115 + else 116 + AwaitServerCertificateRequestOrCertificate13 (session, server_hs_secret, client_hs_secret, log ^ raw) 117 + in 118 + Ok ({ state with machina = Client13 st }, []) 119 + 120 + let answer_certificate state (session : session_data13) server_hs_secret client_hs_secret sigalgs certs raw log = 121 + (* certificates are (cs, ext) list - ext being statusrequest or signed_cert_timestamp *) 122 + let certs = List.map fst certs in 123 + let* peer_certificate, received_certificates, peer_certificate_chain, trust_anchor = 124 + validate_chain state.config.authenticator certs state.config.ip state.config.peer_name 125 + in 126 + let session = 127 + let common_session_data13 = { 128 + session.common_session_data13 with 129 + received_certificates ; peer_certificate_chain ; peer_certificate ; trust_anchor 130 + } in 131 + { session with common_session_data13 } 132 + in 133 + let st = AwaitServerCertificateVerify13 (session, server_hs_secret, client_hs_secret, sigalgs, log ^ raw) in 134 + Ok ({ state with machina = Client13 st }, []) 135 + 136 + let answer_certificate_verify (state : handshake_state) (session : session_data13) server_hs_secret client_hs_secret sigalgs cv raw log = 137 + let tbs = 138 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 session.ciphersuite13)) in 139 + H.(to_raw_string (digest_string log)) 140 + in 141 + let* () = 142 + verify_digitally_signed state.protocol_version 143 + ~context_string:"TLS 1.3, server CertificateVerify" 144 + state.config.signature_algorithms cv tbs 145 + session.common_session_data13.peer_certificate 146 + in 147 + let st = AwaitServerFinished13 (session, server_hs_secret, client_hs_secret, sigalgs, log ^ raw) in 148 + Ok ({ state with machina = Client13 st }, []) 149 + 150 + let answer_certificate_request (state : handshake_state) (session : session_data13) server_hs_secret client_hs_secret extensions raw log = 151 + (* TODO respect extensions (CA, OIDfilter)! *) 152 + let session = 153 + let common_session_data13 = { session.common_session_data13 with client_auth = true } in 154 + { session with common_session_data13 } 155 + in 156 + let sigalgs = Utils.map_find ~f:(function `SignatureAlgorithms s -> Some s | _ -> None) extensions in 157 + let st = AwaitServerCertificate13 (session, server_hs_secret, client_hs_secret, sigalgs, log ^ raw) in 158 + Ok ({ state with machina = Client13 st }, []) 159 + 160 + let answer_finished state (session : session_data13) server_hs_secret client_hs_secret sigalgs fin raw log = 161 + let hash = Ciphersuite.hash13 session.ciphersuite13 in 162 + let f_data = Handshake_crypto13.finished hash server_hs_secret log in 163 + let* () = guard (String.equal fin f_data) (`Fatal (`Handshake (`Message "couldn't verify finished"))) in 164 + let* () = guard (String.length state.hs_fragment = 0) (`Fatal (`Handshake `Fragments)) in 165 + let log = log ^ raw in 166 + let server_app_secret, server_app_ctx, client_app_secret, client_app_ctx = 167 + Handshake_crypto13.app_ctx session.master_secret log 168 + in 169 + let exporter_master_secret = Handshake_crypto13.exporter session.master_secret log in 170 + 171 + let* c_cv, log = 172 + if session.common_session_data13.client_auth then 173 + let own_certificate, own_private_key = 174 + match state.config.Config.own_certificates with 175 + | `Single (chain, priv) -> (chain, Some priv) 176 + | _ -> ([], None) 177 + in 178 + let certificate = 179 + let cs = List.map X509.Certificate.encode_der own_certificate in 180 + Certificate (Writer.assemble_certificates_1_3 "" cs) 181 + in 182 + let cert_raw = Writer.assemble_handshake certificate in 183 + Tracing.hs ~tag:"handshake-out" certificate ; 184 + let log = log ^ cert_raw in 185 + match own_private_key with 186 + | None -> 187 + Ok ([cert_raw], log) 188 + | Some priv -> 189 + let tbs = 190 + let module H = (val Digestif.module_of_hash' hash) in 191 + H.(to_raw_string (digest_string log)) 192 + in 193 + let* signed = 194 + signature `TLS_1_3 ~context_string:"TLS 1.3, client CertificateVerify" 195 + tbs sigalgs state.config.Config.signature_algorithms priv 196 + in 197 + let cv = CertificateVerify signed in 198 + Tracing.hs ~tag:"handshake-out" cv ; 199 + let cv_raw = Writer.assemble_handshake cv in 200 + Ok ([ cert_raw ; cv_raw ], log ^ cv_raw) 201 + else 202 + Ok ([], log) 203 + in 204 + 205 + let myfin = Handshake_crypto13.finished hash client_hs_secret log in 206 + let mfin = Writer.assemble_handshake (Finished myfin) in 207 + 208 + let resumption_secret = Handshake_crypto13.resumption session.master_secret (log ^ mfin) in 209 + let session = { session with resumption_secret ; exporter_master_secret ; client_app_secret ; server_app_secret } in 210 + let machina = Client13 Established13 in 211 + 212 + Tracing.hs ~tag:"handshake-out" (Finished myfin); 213 + 214 + Ok ({ state with machina ; session = `TLS13 session :: state.session }, 215 + List.map (fun data -> `Record (Packet.HANDSHAKE, data)) c_cv @ 216 + [ `Record (Packet.HANDSHAKE, mfin) ; 217 + `Change_dec server_app_ctx ; `Change_enc client_app_ctx ]) 218 + 219 + let answer_session_ticket state st = 220 + (match state.config.ticket_cache with 221 + | None -> () 222 + | Some cache -> 223 + (* looks like we'll need the resumption secret in the state (we can compute once finished is done)! *) 224 + match state.session with 225 + | `TLS13 session :: _ -> 226 + let epoch = epoch_of_session false state.config.Config.peer_name `TLS_1_3 (`TLS13 session) in 227 + let secret = Handshake_crypto13.res_secret 228 + (Ciphersuite.hash13 session.ciphersuite13) 229 + session.resumption_secret st.nonce 230 + in 231 + let issued_at = cache.timestamp () in 232 + let early_data = match Utils.map_find ~f:(function `EarlyDataIndication x -> Some x | _ -> None) st.extensions with 233 + | None -> 0l 234 + | Some x -> x 235 + in 236 + let psk = { identifier = st.ticket ; obfuscation = st.age_add ; secret ; lifetime = st.lifetime ; early_data ; issued_at } in 237 + cache.ticket_granted psk epoch 238 + | _ -> ()); 239 + Ok (state, []) 240 + 241 + let handle_key_update state req = 242 + match state.session with 243 + | `TLS13 session :: _ -> 244 + let* () = guard (String.length state.hs_fragment = 0) (`Fatal (`Handshake `Fragments)) in 245 + let server_app_secret, server_ctx = 246 + Handshake_crypto13.app_secret_n_1 session.master_secret session.server_app_secret 247 + in 248 + let session' = { session with server_app_secret } in 249 + let session', out = match req with 250 + | Packet.UPDATE_NOT_REQUESTED -> session', [] 251 + | Packet.UPDATE_REQUESTED -> 252 + let client_app_secret, client_ctx = 253 + Handshake_crypto13.app_secret_n_1 session.master_secret session.client_app_secret 254 + in 255 + let ku = KeyUpdate Packet.UPDATE_NOT_REQUESTED in 256 + Tracing.hs ~tag:"handshake-out" ku ; 257 + let ku_raw = Writer.assemble_handshake ku in 258 + { session' with client_app_secret }, 259 + [ `Record (Packet.HANDSHAKE, ku_raw); `Change_enc client_ctx ] 260 + in 261 + let session = `TLS13 session' :: state.session in 262 + let state' = { state with machina = Server13 Established13 ; session } in 263 + Ok (state', `Change_dec server_ctx :: out) 264 + | _ -> Error (`Fatal (`Handshake (`Message "couldn't find an earlier session"))) 265 + 266 + let handle_handshake cs hs buf = 267 + let open Reader in 268 + let* handshake = map_reader_error (parse_handshake buf) in 269 + Tracing.hs ~tag:"handshake-in" handshake; 270 + match cs, handshake with 271 + | AwaitServerHello13 (ch, secrets, log), ServerHello sh -> 272 + answer_server_hello hs ch sh secrets buf log 273 + | AwaitServerEncryptedExtensions13 (sd, es, ss, log), EncryptedExtensions ee -> 274 + answer_encrypted_extensions hs sd es ss ee buf log 275 + | AwaitServerCertificateRequestOrCertificate13 (sd, es, ss, log), CertificateRequest cr -> 276 + let* ctx, exts = map_reader_error (parse_certificate_request_1_3 cr) in 277 + (* during handshake, context must be empty! *) 278 + let* () = 279 + guard (ctx = None) 280 + (`Fatal (`Handshake (`Message "certificate request context must be empty"))) 281 + in 282 + answer_certificate_request hs sd es ss exts buf log 283 + | AwaitServerCertificateRequestOrCertificate13 (sd, es, ss, log), Certificate cs -> 284 + let* con, cs = map_reader_error (parse_certificates_1_3 cs) in 285 + (* during handshake, context must be empty! and we'll not get any new certificate from server *) 286 + let* () = 287 + guard (String.length con = 0) 288 + (`Fatal (`Handshake (`Message "certificate context must be empty"))) 289 + in 290 + answer_certificate hs sd es ss None cs buf log 291 + | AwaitServerCertificate13 (sd, es, ss, sigalgs, log), Certificate cs -> 292 + let* con, cs = map_reader_error (parse_certificates_1_3 cs) in 293 + (* during handshake, context must be empty! and we'll not get any new certificate from server *) 294 + let* () = 295 + guard (String.length con = 0) 296 + (`Fatal (`Handshake (`Message "certificate context must be empty"))) 297 + in 298 + answer_certificate hs sd es ss sigalgs cs buf log 299 + | AwaitServerCertificateVerify13 (sd, es, ss, sigalgs, log), CertificateVerify cv -> 300 + answer_certificate_verify hs sd es ss sigalgs cv buf log 301 + | AwaitServerFinished13 (sd, es, ss, sigalgs, log), Finished fin -> 302 + answer_finished hs sd es ss sigalgs fin buf log 303 + | Established13, SessionTicket se -> answer_session_ticket hs se 304 + | Established13, CertificateRequest _ -> 305 + Error (`Fatal (`Unexpected (`Handshake handshake))) (* TODO send out C, CV, F *) 306 + | Established13, KeyUpdate req -> handle_key_update hs req 307 + | _, hs -> Error (`Fatal (`Unexpected (`Handshake hs)))
+550
vendor/opam/tls/lib/handshake_common.ml
··· 1 + open Core 2 + open State 3 + 4 + let src = Logs.Src.create "handshake" ~doc:"TLS handshake" 5 + module Log = (val Logs.src_log src : Logs.LOG) 6 + 7 + let trace_cipher cipher = 8 + Tracing.debug (fun m -> m "%a" Ciphersuite.pp_ciphersuite cipher) 9 + 10 + let empty = function [] -> true | _ -> false 11 + 12 + let change_cipher_spec = 13 + (Packet.CHANGE_CIPHER_SPEC, Writer.assemble_change_cipher_spec) 14 + 15 + let hostname (h : client_hello) : [ `host ] Domain_name.t option = 16 + Utils.map_find ~f:(function `Hostname s -> Some s | _ -> None) h.extensions 17 + 18 + let groups (h : client_hello) = 19 + match Utils.map_find ~f:(function `SupportedGroups g -> Some g | _ -> None) h.extensions with 20 + | Some xs -> 21 + List.fold_left (fun acc g -> 22 + match named_group_to_group g with Some g -> g :: acc | _ -> acc) 23 + [] xs 24 + | None -> [] 25 + 26 + let rec find_matching host certs = 27 + match certs with 28 + | (s::_, _) as chain ::xs -> 29 + if X509.Certificate.supports_hostname s host then 30 + Some chain 31 + else 32 + find_matching host xs 33 + | _::xs -> find_matching host xs (* this should never happen! *) 34 + | [] -> None 35 + 36 + let agreed_cert certs ?f ?signature_algorithms hostname = 37 + let match_host ?default host certs = 38 + match find_matching host certs with 39 + | Some x -> Ok x 40 + | None -> 41 + Option.to_result 42 + ~none:(`Error (`NoMatchingCertificateFound (Domain_name.to_string host))) 43 + default 44 + in 45 + let filter = function 46 + | ([], _) -> false (* cannot happen, TODO: adapt types to avoid this case *) 47 + | (s :: _, _) -> 48 + match f with 49 + | None -> true 50 + | Some f -> f s 51 + in 52 + let filter_sigalg c = 53 + match signature_algorithms with 54 + | None -> true 55 + | Some s -> List.exists (pk_matches_sa (snd c)) s 56 + in 57 + match certs, hostname with 58 + | `None, _ -> Error (`Error `CouldntSelectCertificate) 59 + | `Single c, _ -> 60 + if filter c && filter_sigalg c then Ok c else Error (`Error `CouldntSelectCertificate) 61 + | `Multiple_default (c, _), None -> 62 + if filter c && filter_sigalg c then Ok c else Error (`Error `CouldntSelectCertificate) 63 + | `Multiple_default (c, cs), Some h -> 64 + let default = if filter c && filter_sigalg c then Some c else None in 65 + begin match default, List.filter (fun c -> filter c && filter_sigalg c) cs with 66 + | Some d, cs -> match_host ~default:d h cs 67 + | None, c :: cs -> match_host ~default:c h (c::cs) 68 + | None, [] -> Error (`Error `CouldntSelectCertificate) 69 + end 70 + | `Multiple cs, None -> 71 + begin match List.filter (fun c -> filter c && filter_sigalg c) cs with 72 + | cert :: _ -> Ok cert 73 + | _ -> Error (`Error `CouldntSelectCertificate) 74 + end 75 + | `Multiple cs, Some h -> 76 + match List.filter (fun c -> filter c && filter_sigalg c) cs with 77 + | [ cert ] -> Ok cert 78 + | c :: cs -> match_host ~default:c h (c :: cs) 79 + | [] -> Error (`Error `CouldntSelectCertificate) 80 + 81 + let get_secure_renegotiation exts = 82 + Utils.map_find 83 + exts 84 + ~f:(function `SecureRenegotiation data -> Some data | _ -> None) 85 + 86 + let get_alpn_protocols (ch : client_hello) = 87 + Utils.map_find ~f:(function `ALPN protocols -> Some protocols | _ -> None) ch.extensions 88 + 89 + let alpn_protocol config ch = 90 + match config.Config.alpn_protocols, get_alpn_protocols ch with 91 + | _, None | [], _ -> Ok None 92 + | configured, Some client -> match Utils.first_match client configured with 93 + | Some proto -> Ok (Some proto) 94 + | None -> 95 + (* RFC7301 Section 3.2: 96 + In the event that the server supports no protocols that the client 97 + advertises, then the server SHALL respond with a fatal 98 + "no_application_protocol" alert. *) 99 + Error (`Fatal `No_application_protocol) 100 + 101 + let get_alpn_protocol (sh : server_hello) = 102 + Utils.map_find ~f:(function `ALPN protocol -> Some protocol | _ -> None) sh.extensions 103 + 104 + let empty_common_session_data = { 105 + server_random = "" ; 106 + client_random = "" ; 107 + peer_certificate_chain = [] ; 108 + peer_certificate = None ; 109 + trust_anchor = None ; 110 + received_certificates = [] ; 111 + own_certificate = [] ; 112 + own_private_key = None ; 113 + own_name = None ; 114 + client_auth = false ; 115 + master_secret = "" ; 116 + alpn_protocol = None ; 117 + } 118 + 119 + let empty_session = { 120 + common_session_data = empty_common_session_data ; 121 + client_version = `TLS_1_2 ; 122 + ciphersuite = `DHE_RSA_WITH_AES_256_CBC_SHA ; 123 + group = Some `FFDHE2048 ; 124 + renegotiation = "", "" ; 125 + session_id = "" ; 126 + extended_ms = false ; 127 + tls_unique = "" ; 128 + } 129 + 130 + let empty_session13 cipher = { 131 + common_session_data13 = empty_common_session_data ; 132 + ciphersuite13 = cipher ; 133 + master_secret = Handshake_crypto13.empty cipher ; 134 + exporter_master_secret = "" ; 135 + resumption_secret = "" ; 136 + state = `Established ; 137 + resumed = false ; 138 + client_app_secret = "" ; 139 + server_app_secret = "" ; 140 + } 141 + 142 + let common_session_data_of_epoch (epoch : epoch_data) common_session_data = 143 + { 144 + common_session_data with 145 + peer_certificate = epoch.peer_certificate ; 146 + trust_anchor = epoch.trust_anchor ; 147 + own_certificate = epoch.own_certificate ; 148 + own_private_key = epoch.own_private_key ; 149 + received_certificates = epoch.received_certificates ; 150 + peer_certificate_chain = epoch.peer_certificate_chain ; 151 + master_secret = epoch.master_secret ; 152 + own_name = epoch.own_name ; 153 + alpn_protocol = epoch.alpn_protocol ; 154 + } 155 + 156 + let session_of_epoch (epoch : epoch_data) : session_data = 157 + let empty = empty_session in 158 + let common_session_data = common_session_data_of_epoch epoch empty.common_session_data in 159 + { empty with 160 + common_session_data ; 161 + ciphersuite = epoch.ciphersuite ; 162 + session_id = epoch.session_id ; 163 + extended_ms = epoch.extended_ms ; 164 + } 165 + 166 + let session13_of_epoch cipher (epoch : epoch_data) : session_data13 = 167 + let empty = empty_session13 cipher in 168 + let common_session_data13 = common_session_data_of_epoch epoch empty.common_session_data13 in 169 + { empty with 170 + common_session_data13 ; 171 + ciphersuite13 = cipher ; 172 + state = epoch.state ; 173 + exporter_master_secret = epoch.exporter_master_secret ; 174 + } 175 + 176 + let supported_protocol_version (min, max) v = 177 + if compare_tls_version min v > 0 then 178 + None 179 + else if compare_tls_version v max > 0 then 180 + None 181 + else 182 + Some v 183 + 184 + let to_client_ext_type = function 185 + | `Hostname _ -> `Hostname 186 + | `MaxFragmentLength _ -> `MaxFragmentLength 187 + | `SupportedGroups _ -> `SupportedGroups 188 + | `ECPointFormats -> `ECPointFormats 189 + | `SecureRenegotiation _ -> `SecureRenegotiation 190 + | `Padding _ -> `Padding 191 + | `SignatureAlgorithms _ -> `SignatureAlgorithms 192 + | `UnknownExtension _ -> `UnknownExtension 193 + | `ExtendedMasterSecret -> `ExtendedMasterSecret 194 + | `ALPN _ -> `ALPN 195 + | `KeyShare _ -> `KeyShare 196 + | `EarlyDataIndication -> `EarlyDataIndication 197 + | `PreSharedKeys _ -> `PreSharedKey 198 + | `Draft _ -> `Draft 199 + | `SupportedVersions _ -> `SupportedVersion 200 + | `PostHandshakeAuthentication -> `PostHandshakeAuthentication 201 + | `Cookie _ -> `Cookie 202 + | `PskKeyExchangeModes _ -> `PskKeyExchangeMode 203 + 204 + let to_server_ext_type = function 205 + | `Hostname -> `Hostname 206 + | `MaxFragmentLength _ -> `MaxFragmentLength 207 + | `ECPointFormats -> `ECPointFormats 208 + | `SecureRenegotiation _ -> `SecureRenegotiation 209 + | `UnknownExtension _ -> `UnknownExtension 210 + | `ExtendedMasterSecret -> `ExtendedMasterSecret 211 + | `ALPN _ -> `ALPN 212 + | `KeyShare _ -> `KeyShare 213 + | `EarlyDataIndication -> `EarlyDataIndication 214 + | `PreSharedKey _ -> `PreSharedKey 215 + | `Draft _ -> `Draft 216 + | `SelectedVersion _ -> `SupportedVersion 217 + 218 + let extension_types t exts = List.( 219 + exts |> map t 220 + |> filter @@ function `UnknownExtension -> false | _ -> true 221 + ) 222 + 223 + (* a server hello may only contain extensions which are also in the client hello *) 224 + (* RFC5246, 7.4.7.1 225 + An extension type MUST NOT appear in the ServerHello unless the same 226 + extension type appeared in the corresponding ClientHello. If a 227 + client receives an extension type in ServerHello that it did not 228 + request in the associated ClientHello, it MUST abort the handshake 229 + with an unsupported_extension fatal alert. *) 230 + let server_exts_subset_of_client sexts cexts = 231 + let (sexts', cexts') = 232 + (extension_types to_server_ext_type sexts, extension_types to_client_ext_type cexts) in 233 + Utils.List_set.subset sexts' (`Cookie :: cexts') 234 + 235 + module Group = struct 236 + type t = Packet.named_group 237 + let compare = Stdlib.compare 238 + end 239 + 240 + module GroupSet = Set.Make(Group) 241 + 242 + (* Set.of_list appeared only in 4.02, for 4.01 compatibility *) 243 + let of_list xs = List.fold_right GroupSet.add xs GroupSet.empty 244 + 245 + let client_hello_valid version (ch : client_hello) = 246 + (* match ch.version with 247 + | TLS_1_0 -> 248 + if List.mem TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA ch.ciphersuites then 249 + return () 250 + else 251 + fail HANDSHAKE_FAILURE 252 + | TLS_1_1 -> 253 + if List.mem TLS_RSA_WITH_3DES_EDE_CBC_SHA ch.ciphersuites then 254 + return () 255 + else 256 + fail HANDSHAKE_FAILURE 257 + | TLS_1_2 -> 258 + if List.mem TLS_RSA_WITH_AES_128_CBC_SHA ch.ciphersuites then 259 + return () 260 + else 261 + fail HANDSHAKE_FAILURE *) 262 + let sig_alg = 263 + Utils.map_find 264 + ~f:(function `SignatureAlgorithms sa -> Some sa | _ -> None) 265 + ch.extensions 266 + and key_share = 267 + Utils.map_find 268 + ~f:(function `KeyShare ks -> Some ks | _ -> None) 269 + ch.extensions 270 + and groups = 271 + Utils.map_find 272 + ~f:(function `SupportedGroups gs -> Some gs | _ -> None) 273 + ch.extensions 274 + in 275 + 276 + let version_good = match version with 277 + | `TLS_1_2 | `TLS_1_X _ -> Ok () 278 + | `TLS_1_3 -> 279 + ( let good_sig_alg = 280 + List.exists (fun sa -> List.mem sa Config.supported_signature_algorithms) 281 + in 282 + match sig_alg with 283 + | None -> Error (`Fatal (`Missing_extension "signature algorithms")) 284 + | Some sig_alg when good_sig_alg sig_alg -> 285 + ( match key_share, groups with 286 + | None, _ -> Error (`Fatal (`Missing_extension "key share")) 287 + | _, None -> Error (`Fatal (`Missing_extension "supported group")) 288 + | Some ks, Some gs -> 289 + match 290 + Utils.List_set.is_proper_set gs, 291 + Utils.List_set.is_proper_set (List.map fst ks), 292 + GroupSet.subset (of_list (List.map fst ks)) (of_list gs) 293 + with 294 + | true, true, true -> Ok () 295 + | false, _, _ -> Error (`Fatal (`Handshake (`Message "supported group is not a set"))) 296 + | _, false, _ -> Error (`Fatal (`Handshake (`Message "key share is not a set"))) 297 + | _, _, false -> Error (`Fatal (`Handshake (`Message "key share is not a subset of supported group")) )) 298 + | Some _ -> Error (`Fatal (`Handshake (`Message "no good signature algorithms"))) 299 + ) 300 + | `SSL_3 | `TLS_1_0 | `TLS_1_1 -> Ok () 301 + in 302 + 303 + let share_ciphers = 304 + match 305 + Utils.first_match (List.filter_map Ciphersuite.any_ciphersuite_to_ciphersuite ch.ciphersuites) Config.Ciphers.supported 306 + with 307 + | None -> false 308 + | Some _ -> true 309 + in 310 + match 311 + not (empty ch.ciphersuites), 312 + share_ciphers, 313 + Utils.List_set.is_proper_set (extension_types to_client_ext_type ch.extensions) 314 + with 315 + | true, true, true -> version_good 316 + | false, _, _ -> Error (`Fatal (`Handshake (`Message "ciphersuites is empty"))) 317 + | _, false, _ -> Error (`Fatal (`Handshake (`Message "no supported ciphersuite"))) 318 + | _, _, false -> Error (`Fatal (`Handshake (`Message "extensions is not a set"))) 319 + 320 + 321 + let server_hello_valid (sh : server_hello) = 322 + (* let open Ciphersuite in *) 323 + Utils.List_set.is_proper_set (extension_types to_server_ext_type sh.extensions) 324 + (* TODO: 325 + - EC stuff must be present if EC ciphersuite chosen 326 + *) 327 + 328 + let to_sign_1_3 context_string = 329 + (* input is prepended by 64 * 0x20 (to avoid cross-version attacks) *) 330 + (* input for signature now contains also a context string *) 331 + let len = match context_string with 332 + | None -> 64 + 1 333 + | Some v -> 64 + String.length v + 1 in 334 + let buf = Bytes.create len in 335 + Bytes.fill buf 0 64 '\x20'; 336 + begin match context_string with 337 + | None -> () 338 + | Some v -> Bytes.blit_string v 0 buf 64 (String.length v) end; 339 + Bytes.set buf (Bytes.length buf - 1) '\x00'; 340 + Bytes.unsafe_to_string buf 341 + 342 + let signature version ?context_string data client_sig_algs signature_algorithms (private_key : X509.Private_key.t) = 343 + match version with 344 + | `TLS_1_0 | `TLS_1_1 -> 345 + let* signed = 346 + match private_key with 347 + | `RSA key -> 348 + begin try 349 + let data = 350 + Digestif.(MD5.(to_raw_string (digest_string data)) ^ 351 + SHA1.(to_raw_string (digest_string data))) 352 + in 353 + Ok (Mirage_crypto_pk.Rsa.PKCS1.sig_encode ~key data) 354 + with Mirage_crypto_pk.Rsa.Insufficient_key -> 355 + Error (`Fatal (`Bad_certificate "RSA key too small")) 356 + end 357 + | k -> 358 + (* not passing ~scheme: only non-RSA keys sig scheme is trivial *) 359 + Result.map_error 360 + (function `Msg m -> `Fatal (`Handshake (`Message ("signing failed: " ^ m)))) 361 + (X509.Private_key.sign `SHA1 k (`Message data)) 362 + in 363 + Ok (Writer.assemble_digitally_signed signed) 364 + | `TLS_1_2 -> 365 + let* sig_alg = 366 + match client_sig_algs with 367 + | None -> 368 + Ok (match private_key with 369 + | `RSA _ -> `RSA_PKCS1_SHA1 370 + | `ED25519 _ -> `ED25519 371 + | _ -> `ECDSA_SECP256R1_SHA1) 372 + | Some client_algos -> 373 + Option.to_result 374 + ~none:(`Error (`NoConfiguredSignatureAlgorithm client_algos)) 375 + (Utils.first_match client_algos (List.filter (pk_matches_sa private_key) signature_algorithms)) 376 + in 377 + let scheme = signature_scheme_of_signature_algorithm sig_alg 378 + and hash = hash_of_signature_algorithm sig_alg 379 + in 380 + let* signature = 381 + Result.map_error (function `Msg m -> `Fatal (`Handshake (`Message ("signing failed: " ^ m)))) 382 + (X509.Private_key.sign hash ~scheme private_key (`Message data)) 383 + in 384 + Ok (Writer.assemble_digitally_signed_1_2 sig_alg signature) 385 + | `TLS_1_3 -> 386 + let to_sign = 387 + let prefix = to_sign_1_3 context_string in 388 + prefix ^ data 389 + in 390 + let* sig_alg = 391 + let* client_algos = 392 + (* 8446 4.2.3 "client MUST send signatureAlgorithms" *) 393 + Option.to_result 394 + ~none:(`Error (`NoConfiguredSignatureAlgorithm [])) 395 + client_sig_algs 396 + in 397 + let sa = List.filter tls13_sigalg signature_algorithms in 398 + let sa = List.filter (pk_matches_sa private_key) sa in 399 + Option.to_result 400 + ~none:(`Error (`NoConfiguredSignatureAlgorithm client_algos)) 401 + (Utils.first_match client_algos sa) 402 + in 403 + let scheme = signature_scheme_of_signature_algorithm sig_alg 404 + and hash = hash_of_signature_algorithm sig_alg 405 + in 406 + let* signature = 407 + Result.map_error (function `Msg m -> `Fatal (`Handshake (`Message ("signing failed: " ^ m)))) 408 + (X509.Private_key.sign hash ~scheme private_key (`Message to_sign)) 409 + in 410 + Ok (Writer.assemble_digitally_signed_1_2 sig_alg signature) 411 + 412 + let peer_key = function 413 + | None -> Error (`Fatal (`Bad_certificate "none received")) 414 + | Some cert -> Ok (X509.Certificate.public_key cert) 415 + 416 + let verify_digitally_signed version ?context_string sig_algs data signature_data certificate = 417 + let* pubkey = peer_key certificate in 418 + match version with 419 + | `TLS_1_0 | `TLS_1_1 -> 420 + let* signature = map_reader_error (Reader.parse_digitally_signed data) in 421 + begin match pubkey with 422 + | `RSA key -> 423 + let* raw = 424 + Option.to_result 425 + ~none:(`Fatal (`Handshake (`Message "couldn't decode PKCS1"))) 426 + (Mirage_crypto_pk.Rsa.PKCS1.sig_decode ~key signature) 427 + in 428 + let computed = 429 + Digestif.(MD5.(to_raw_string (digest_string signature_data)) ^ 430 + SHA1.(to_raw_string (digest_string signature_data))) 431 + in 432 + guard (String.equal raw computed) 433 + (`Fatal (`Handshake (`Message "RSA PKCS1 raw <> computed"))) 434 + | key -> 435 + Result.map_error 436 + (function `Msg m -> `Fatal (`Handshake (`Message ("signature verification failed: " ^ m)))) 437 + (X509.Public_key.verify `SHA1 ~signature key (`Message signature_data)) 438 + end 439 + | `TLS_1_2 -> 440 + let* sig_alg, signature = 441 + map_reader_error (Reader.parse_digitally_signed_1_2 data) 442 + in 443 + let* () = 444 + guard (List.mem sig_alg sig_algs) 445 + (`Error (`NoConfiguredSignatureAlgorithm sig_algs)) 446 + in 447 + let hash = hash_of_signature_algorithm sig_alg 448 + and scheme = signature_scheme_of_signature_algorithm sig_alg 449 + in 450 + Result.map_error 451 + (function `Msg m -> `Fatal (`Handshake (`Message ("signature verification failed: " ^ m)))) 452 + (X509.Public_key.verify hash ~scheme ~signature pubkey (`Message signature_data)) 453 + | `TLS_1_3 -> 454 + let* sig_alg, signature = 455 + map_reader_error (Reader.parse_digitally_signed_1_2 data) 456 + in 457 + let* () = 458 + guard (List.mem sig_alg sig_algs) 459 + (`Error (`NoConfiguredSignatureAlgorithm sig_algs)) 460 + in 461 + let hash = hash_of_signature_algorithm sig_alg 462 + and scheme = signature_scheme_of_signature_algorithm sig_alg 463 + and data = 464 + let prefix = to_sign_1_3 context_string in 465 + prefix ^ signature_data 466 + in 467 + Result.map_error 468 + (function `Msg m -> `Fatal (`Handshake (`Message ("signature verification failed: " ^ m)))) 469 + (X509.Public_key.verify hash ~scheme ~signature pubkey (`Message data)) 470 + 471 + let validate_chain authenticator certificates ip hostname = 472 + let authenticate authenticator host certificates = 473 + Result.map_error 474 + (fun err -> `Error (`AuthenticationFailure err)) 475 + (authenticator ?ip ~host certificates) 476 + 477 + and key_size min cs = 478 + let check c = 479 + match X509.Certificate.public_key c with 480 + | `RSA key -> Mirage_crypto_pk.Rsa.pub_bits key >= min 481 + | _ -> true 482 + in 483 + guard (List.for_all check cs) (`Fatal (`Bad_certificate "key too small")) 484 + 485 + and parse_certificates certs = 486 + let certificates = 487 + let f cs = 488 + match X509.Certificate.decode_der cs with 489 + | Ok c -> Some c 490 + | Error `Msg msg -> 491 + Log.warn (fun m -> m "cannot decode certificate %s:@.%a" msg 492 + (Ohex.pp_hexdump ()) cs); 493 + None 494 + in 495 + List.filter_map f certs 496 + in 497 + let* () = 498 + guard (List.length certs = List.length certificates) 499 + (`Fatal (`Bad_certificate "couldn't decode some certificates")) 500 + in 501 + Ok certificates 502 + in 503 + 504 + (* RFC5246: must be x509v3, take signaturealgorithms into account! *) 505 + (* RFC2246/4346: is generally x509v3, signing algorithm for certificate _must_ be same as algorithm for certificate key *) 506 + let* certs = parse_certificates certificates in 507 + let server = match certs with 508 + | s::_ -> Some s 509 + | [] -> None 510 + in 511 + match authenticator with 512 + | None -> Ok (server, certs, [], None) 513 + | Some authenticator -> 514 + let* anchor = authenticate authenticator hostname certs in 515 + let* () = key_size Config.min_rsa_key_size certs in 516 + Ok (Option.fold ~none:(server, certs, [], None) 517 + ~some:(fun (chain, anchor) -> (server, certs, chain, Some anchor)) 518 + anchor) 519 + 520 + let output_key_update ~request state = 521 + let hs = state.handshake in 522 + match hs.session with 523 + | `TLS13 session :: _ -> 524 + let* session', encryptor = 525 + match hs.machina with 526 + | Client13 Established13 -> 527 + let client_app_secret, client_ctx = 528 + Handshake_crypto13.app_secret_n_1 529 + session.master_secret session.client_app_secret 530 + in 531 + Ok ({ session with client_app_secret }, client_ctx) 532 + | Server13 Established13 -> 533 + let server_app_secret, server_ctx = 534 + Handshake_crypto13.app_secret_n_1 535 + session.master_secret session.server_app_secret 536 + in 537 + Ok ({ session with server_app_secret }, server_ctx) 538 + | _ -> Error (`Fatal (`Handshake (`Message "invalid state for key update"))) 539 + in 540 + let handshake = { hs with session = `TLS13 session' :: hs.session } in 541 + let ku = 542 + let p = 543 + Packet.(if request then UPDATE_REQUESTED else UPDATE_NOT_REQUESTED) 544 + in 545 + KeyUpdate p 546 + in 547 + let out = Writer.assemble_handshake ku in 548 + Ok ({ state with encryptor = Some encryptor ; handshake }, 549 + (Packet.HANDSHAKE, out)) 550 + | _ -> Error (`Fatal (`Handshake (`Message "no earlier session found")))
+111
vendor/opam/tls/lib/handshake_crypto.ml
··· 1 + open State 2 + 3 + let halve secret = 4 + let size = String.length secret in 5 + let half = size - size / 2 in 6 + String.(sub secret 0 half, sub secret (size - half) half) 7 + 8 + let p_hash (hmac, hmac_n) key seed len = 9 + let rec expand a to_go = 10 + let res = hmac ~key (a ^ seed) in 11 + if to_go > hmac_n then 12 + res ^ expand (hmac ~key a) (to_go - hmac_n) 13 + else String.sub res 0 to_go 14 + in 15 + expand (hmac ~key seed) len 16 + 17 + let prf_mac = function 18 + | `RSA_WITH_AES_256_GCM_SHA384 19 + | `DHE_RSA_WITH_AES_256_GCM_SHA384 20 + | `ECDHE_RSA_WITH_AES_256_GCM_SHA384 21 + | `ECDHE_RSA_WITH_AES_256_CBC_SHA384 22 + | `ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 23 + | `ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -> (module Digestif.SHA384 : Digestif.S) 24 + | _ -> (module Digestif.SHA256 : Digestif.S) 25 + 26 + let pseudo_random_function version cipher len secret label seed = 27 + let labelled = label ^ seed in 28 + match version with 29 + | `TLS_1_1 | `TLS_1_0 -> 30 + let (s1, s2) = halve secret in 31 + let md5 = p_hash ((fun ~key s -> Digestif.MD5.(to_raw_string (hmac_string ~key s))), Digestif.MD5.digest_size) s1 labelled len 32 + and sha = p_hash ((fun ~key s -> Digestif.SHA1.(to_raw_string (hmac_string ~key s))), Digestif.SHA1.digest_size) s2 labelled len in 33 + Mirage_crypto.Uncommon.xor md5 sha 34 + | `TLS_1_2 -> 35 + let module D = (val (prf_mac cipher)) in 36 + p_hash ((fun ~key s -> D.(to_raw_string (hmac_string ~key s))), D.digest_size) secret labelled len 37 + 38 + let key_block version cipher len master_secret seed = 39 + pseudo_random_function version cipher len master_secret "key expansion" seed 40 + 41 + let hash version cipher data = 42 + match version with 43 + | `TLS_1_0 | `TLS_1_1 -> Digestif.(MD5.(to_raw_string (digest_string data)) ^ SHA1.(to_raw_string (digest_string data))) 44 + | `TLS_1_2 -> 45 + let module H = (val prf_mac cipher) in 46 + H.(to_raw_string (digest_string data)) 47 + 48 + let finished version cipher master_secret label ps = 49 + let data = String.concat "" ps in 50 + let seed = hash version cipher data in 51 + pseudo_random_function version cipher 12 master_secret label seed 52 + 53 + let divide_keyblock key mac iv buf = 54 + let c_mac, rt0 = Core.split_str buf mac in 55 + let s_mac, rt1 = Core.split_str rt0 mac in 56 + let c_key, rt2 = Core.split_str rt1 key in 57 + let s_key, rt3 = Core.split_str rt2 key in 58 + let c_iv , s_iv = Core.split_str rt3 iv 59 + in 60 + (c_mac, s_mac, c_key, s_key, c_iv, s_iv) 61 + 62 + let derive_master_secret version (session : session_data) premaster log = 63 + let prf = pseudo_random_function version session.ciphersuite 48 premaster in 64 + if session.extended_ms then 65 + let session_hash = 66 + let data = String.concat "" log in 67 + hash version session.ciphersuite data 68 + in 69 + prf "extended master secret" session_hash 70 + else 71 + prf "master secret" (session.common_session_data.client_random ^ session.common_session_data.server_random) 72 + 73 + let initialise_crypto_ctx version (session : session_data) = 74 + let open Ciphersuite in 75 + let client_random = session.common_session_data.client_random 76 + and server_random = session.common_session_data.server_random 77 + and master = session.common_session_data.master_secret 78 + and cipher = session.ciphersuite 79 + in 80 + 81 + let pp = ciphersuite_privprot cipher in 82 + 83 + let c_mac, s_mac, c_key, s_key, c_iv, s_iv = 84 + let iv_l = match version with 85 + | `TLS_1_0 -> Some () 86 + | _ -> None 87 + in 88 + let key_len, iv_len, mac_len = Ciphersuite.key_length iv_l pp in 89 + let kblen = 2 * key_len + 2 * mac_len + 2 * iv_len 90 + and rand = server_random ^ client_random 91 + in 92 + let keyblock = key_block version cipher kblen master rand in 93 + divide_keyblock key_len mac_len iv_len keyblock 94 + in 95 + 96 + let context cipher_k iv mac_k = 97 + let open Crypto.Ciphers in 98 + let cipher_st = 99 + let iv_mode = match version with 100 + | `TLS_1_0 -> Iv iv 101 + | _ -> Random_iv 102 + in 103 + get_cipher ~secret:cipher_k ~hmac_secret:mac_k ~iv_mode ~nonce:iv pp 104 + and sequence = 0L in 105 + { cipher_st ; sequence } 106 + in 107 + 108 + let c_context = context c_key c_iv c_mac 109 + and s_context = context s_key s_iv s_mac in 110 + 111 + (c_context, s_context)
+9
vendor/opam/tls/lib/handshake_crypto.mli
··· 1 + open State 2 + 3 + val derive_master_secret : Core.tls_before_13 -> session_data -> string -> string list -> Core.master_secret 4 + val initialise_crypto_ctx : Core.tls_before_13 -> session_data -> (crypto_context * crypto_context) 5 + val finished : Core.tls_before_13 -> Ciphersuite.ciphersuite -> string -> string -> string list -> string 6 + 7 + (** [pseudo_random_function version cipher length secret label seed] *) 8 + val pseudo_random_function : Core.tls_before_13 -> Ciphersuite.ciphersuite -> 9 + int -> string -> string -> string -> string
+183
vendor/opam/tls/lib/handshake_crypto13.ml
··· 1 + open Core 2 + 3 + let cdiv (x : int) (y : int) = 4 + if x > 0 && y > 0 then (x + y - 1) / y 5 + else if x < 0 && y < 0 then (x + y + 1) / y 6 + else x / y 7 + 8 + let left_pad_dh group msg = 9 + let bytes = cdiv (Mirage_crypto_pk.Dh.modulus_size group) 8 in 10 + let padding = String.make (bytes - String.length msg) '\x00' in 11 + padding ^ msg 12 + 13 + let not_all_zero r = 14 + let* str = r in 15 + try 16 + for i = 0 to String.length str - 1 do 17 + if String.unsafe_get str i != '\x00' then raise_notrace Not_found; 18 + done; 19 + Error (`Fatal (`Handshake (`BadDH "all zero"))) 20 + with Not_found -> Ok str 21 + 22 + let dh_shared secret share = 23 + (* RFC 8556, Section 7.4.1 - we need zero-padding on the left *) 24 + let map_ecdh_error = 25 + Result.map_error (fun e -> `Fatal (`Handshake (`BadECDH e))) 26 + in 27 + let open Mirage_crypto_ec in 28 + not_all_zero 29 + (match secret with 30 + | `Finite_field secret -> 31 + let group = secret.Mirage_crypto_pk.Dh.group in 32 + let bits = Mirage_crypto_pk.Dh.modulus_size group in 33 + let* () = 34 + (* truncated share, better reject this *) 35 + guard (String.length share = cdiv bits 8) 36 + (`Fatal (`Handshake (`BadDH "truncated"))) 37 + in 38 + let* shared = 39 + Option.to_result 40 + ~none:(`Fatal (`Handshake (`BadDH "invalid FF"))) 41 + (Mirage_crypto_pk.Dh.shared secret share) 42 + in 43 + Ok (left_pad_dh group shared) 44 + | `P256 priv -> map_ecdh_error (P256.Dh.key_exchange priv share) 45 + | `P384 priv -> map_ecdh_error (P384.Dh.key_exchange priv share) 46 + | `P521 priv -> map_ecdh_error (P521.Dh.key_exchange priv share) 47 + | `X25519 priv -> map_ecdh_error (X25519.key_exchange priv share)) 48 + 49 + let dh_gen_key group = 50 + (* RFC 8556, Section 4.2.8.1 - we need zero-padding on the left *) 51 + match Core.group_to_impl group with 52 + | `Finite_field mc_group -> 53 + let sec, shared = Mirage_crypto_pk.Dh.gen_key mc_group in 54 + `Finite_field sec, left_pad_dh mc_group shared 55 + | `P256 -> 56 + let secret, shared = Mirage_crypto_ec.P256.Dh.gen_key () in 57 + `P256 secret, shared 58 + | `P384 -> 59 + let secret, shared = Mirage_crypto_ec.P384.Dh.gen_key () in 60 + `P384 secret, shared 61 + | `P521 -> 62 + let secret, shared = Mirage_crypto_ec.P521.Dh.gen_key () in 63 + `P521 secret, shared 64 + | `X25519 -> 65 + let secret, shared = Mirage_crypto_ec.X25519.gen_key () in 66 + `X25519 secret, shared 67 + 68 + let trace tag cs = Tracing.cs ~tag:("crypto " ^ tag) cs 69 + 70 + let pp_hash_k_n ciphersuite = 71 + let open Ciphersuite in 72 + let pp = privprot13 ciphersuite 73 + and hash = hash13 ciphersuite 74 + in 75 + let k, n = kn_13 pp in 76 + (pp, hash, k, n) 77 + 78 + let hkdflabel label context length = 79 + let lbl = "tls13 " ^ label in 80 + let len_llen = Bytes.create 3 in 81 + Bytes.set_uint16_be len_llen 0 length; 82 + Bytes.set_uint8 len_llen 2 (String.length lbl); 83 + let clen = String.make 1 (Char.unsafe_chr (String.length context)) in 84 + let lbl = String.concat "" 85 + [ Bytes.unsafe_to_string len_llen ; 86 + lbl ; 87 + clen ; 88 + context ] 89 + in 90 + trace "hkdflabel" lbl ; 91 + lbl 92 + 93 + let derive_secret_no_hash hash prk ?length ?(ctx = "") label = 94 + let length = match length with 95 + | None -> 96 + let module H = (val Digestif.module_of_hash' hash) in 97 + H.digest_size 98 + | Some x -> x 99 + in 100 + let info = hkdflabel label ctx length in 101 + trace "prk" prk ; 102 + let key = Hkdf.expand ~hash ~prk ~info length in 103 + trace ("derive_secret: " ^ label) key ; 104 + key 105 + 106 + let derive_secret t label log = 107 + let module H = (val Digestif.module_of_hash' t.State.hash) in 108 + let ctx = H.(to_raw_string (digest_string log)) in 109 + trace "derive secret ctx" ctx ; 110 + derive_secret_no_hash t.State.hash t.State.secret ~ctx label 111 + 112 + let empty cipher = { 113 + State.secret = "" ; 114 + cipher ; 115 + hash = Ciphersuite.hash13 cipher 116 + } 117 + 118 + let derive t secret_ikm = 119 + let salt = 120 + if String.equal t.State.secret "" then 121 + "" 122 + else 123 + derive_secret t "derived" "" 124 + in 125 + trace "derive: secret_ikm" secret_ikm ; 126 + trace "derive: salt" salt ; 127 + let secret = Hkdf.extract ~hash:t.State.hash ~salt secret_ikm in 128 + trace "derive (extracted secret)" secret ; 129 + { t with State.secret } 130 + 131 + let traffic_key cipher prk = 132 + let _, hash, key_len, iv_len = pp_hash_k_n cipher in 133 + let key_info = hkdflabel "key" "" key_len in 134 + let key = Hkdf.expand ~hash ~prk ~info:key_info key_len in 135 + let iv_info = hkdflabel "iv" "" iv_len in 136 + let iv = Hkdf.expand ~hash ~prk ~info:iv_info iv_len in 137 + (key, iv) 138 + 139 + let ctx t label secret = 140 + let secret, nonce = traffic_key t.State.cipher secret in 141 + trace (label ^ " secret") secret ; 142 + trace (label ^ " nonce") nonce ; 143 + let pp = Ciphersuite.privprot13 t.State.cipher in 144 + { State.sequence = 0L ; cipher_st = Crypto.Ciphers.get_aead_cipher ~secret ~nonce pp } 145 + 146 + let early_traffic t log = 147 + let secret = derive_secret t "c e traffic" log in 148 + (secret, ctx t "client early traffic" secret) 149 + 150 + let hs_ctx t log = 151 + Tracing.cs ~tag:"hs ctx with sec" t.State.secret ; 152 + Tracing.cs ~tag:"log is" log ; 153 + let server_handshake_traffic_secret = derive_secret t "s hs traffic" log 154 + and client_handshake_traffic_secret = derive_secret t "c hs traffic" log 155 + in 156 + (server_handshake_traffic_secret, 157 + ctx t "server handshake traffic" server_handshake_traffic_secret, 158 + client_handshake_traffic_secret, 159 + ctx t "client handshake traffic" client_handshake_traffic_secret) 160 + 161 + let app_ctx t log = 162 + let server_application_traffic_secret = derive_secret t "s ap traffic" log 163 + and client_application_traffic_secret = derive_secret t "c ap traffic" log 164 + in 165 + (server_application_traffic_secret, 166 + ctx t "server application traffic" server_application_traffic_secret, 167 + client_application_traffic_secret, 168 + ctx t "client application traffic" client_application_traffic_secret) 169 + 170 + let app_secret_n_1 t app_secret = 171 + let secret = derive_secret_no_hash t.State.hash app_secret "traffic upd" in 172 + secret, ctx t "traffic update" secret 173 + 174 + let exporter t log = derive_secret t "exp master" log 175 + let resumption t log = derive_secret t "res master" log 176 + 177 + let res_secret hash secret nonce = 178 + derive_secret_no_hash hash secret ~ctx:nonce "resumption" 179 + 180 + let finished hash secret data = 181 + let module H = (val Digestif.module_of_hash' hash) in 182 + let key = derive_secret_no_hash hash secret "finished" in 183 + H.(to_raw_string (hmac_string ~key (to_raw_string (digest_string data))))
+662
vendor/opam/tls/lib/handshake_server.ml
··· 1 + open Core 2 + open State 3 + open Handshake_common 4 + open Config 5 + 6 + let state_version state = match state.protocol_version with 7 + | #tls_before_13 as v -> v 8 + | _ -> assert false 9 + 10 + let hello_request state = 11 + if state.config.use_reneg then 12 + let hr = HelloRequest in 13 + Tracing.hs ~tag:"handshake-out" hr ; 14 + let state = { state with machina = Server AwaitClientHelloRenegotiate } in 15 + Ok (state, [`Record (Packet.HANDSHAKE, Writer.assemble_handshake hr)]) 16 + else 17 + Error (`Fatal (`Handshake (`Message "renegotation is not supported"))) 18 + 19 + 20 + let answer_client_finished state (session : session_data) client_fin raw log = 21 + let client, server = 22 + let checksum = Handshake_crypto.finished (state_version state) 23 + session.ciphersuite session.common_session_data.master_secret 24 + in 25 + (checksum "client finished" log, checksum "server finished" (log @ [raw])) 26 + in 27 + let* () = 28 + guard (String.equal client client_fin) 29 + (`Fatal (`Handshake (`Message "couldn't verify finished"))) 30 + in 31 + let session = { session with tls_unique = client } in 32 + let fin = Finished server in 33 + let fin_raw = Writer.assemble_handshake fin in 34 + (* we really do not want to have any leftover handshake fragments *) 35 + let* () = 36 + guard (String.length state.hs_fragment = 0) 37 + (`Fatal (`Handshake `Fragments)) 38 + in 39 + let session = { session with renegotiation = (client, server) } 40 + and machina = Server Established 41 + in 42 + Tracing.hs ~tag:"handshake-out" fin ; 43 + Ok ({ state with machina ; session = `TLS session :: state.session }, 44 + [`Record (Packet.HANDSHAKE, fin_raw)]) 45 + 46 + let answer_client_finished_resume state (session : session_data) server_verify client_fin _raw log = 47 + let client_verify = 48 + Handshake_crypto.finished (state_version state) session.ciphersuite session.common_session_data.master_secret "client finished" log 49 + in 50 + let* () = 51 + guard (String.equal client_verify client_fin) 52 + (`Fatal (`Handshake (`Message "couldn't verify finished"))) 53 + in 54 + (* we really do not want to have any leftover handshake fragments *) 55 + let* () = 56 + guard (String.length state.hs_fragment = 0) 57 + (`Fatal (`Handshake `Fragments)) 58 + in 59 + let session = { session with renegotiation = (client_verify, server_verify) } 60 + and machina = Server Established 61 + in 62 + Ok ({ state with machina ; session = `TLS session :: state.session }, []) 63 + 64 + let establish_master_secret state (session : session_data) premastersecret raw log = 65 + let log = log @ [raw] in 66 + let master_secret = Handshake_crypto.derive_master_secret 67 + (state_version state) session premastersecret log 68 + in 69 + let session = 70 + let common_session_data = { session.common_session_data with master_secret } in 71 + { session with common_session_data } 72 + in 73 + let client_ctx, server_ctx = 74 + Handshake_crypto.initialise_crypto_ctx (state_version state) session 75 + in 76 + let machina = 77 + match session.common_session_data.peer_certificate with 78 + | None -> AwaitClientChangeCipherSpec (session, server_ctx, client_ctx, log) 79 + | Some _ -> AwaitClientCertificateVerify (session, server_ctx, client_ctx, log) 80 + in 81 + Tracing.cs ~tag:"master-secret" master_secret ; 82 + ({ state with machina = Server machina }, []) 83 + 84 + let private_key (session : session_data) = 85 + match session.common_session_data.own_private_key with 86 + | Some priv -> Ok priv 87 + | None -> Error (`Fatal (`Handshake (`Message "couldn't locate private key"))) 88 + 89 + let validate_certs certs authenticator ip (session : session_data) = 90 + let* peer_certificate, received_certificates, peer_certificate_chain, trust_anchor = 91 + validate_chain authenticator certs ip None 92 + in 93 + let common_session_data = { 94 + session.common_session_data with 95 + received_certificates ; 96 + peer_certificate ; 97 + peer_certificate_chain ; 98 + trust_anchor 99 + } in 100 + Ok { session with common_session_data } 101 + 102 + let answer_client_certificate_RSA state (session : session_data) certs raw log = 103 + let* session = 104 + validate_certs certs state.config.authenticator state.config.ip session 105 + in 106 + let machina = AwaitClientKeyExchange_RSA (session, log @ [raw]) in 107 + Ok ({ state with machina = Server machina }, []) 108 + 109 + let answer_client_certificate_DHE state (session : session_data) dh_sent certs raw log = 110 + let* session = 111 + validate_certs certs state.config.authenticator state.config.ip session 112 + in 113 + let machina = AwaitClientKeyExchange_DHE (session, dh_sent, log @ [raw]) in 114 + Ok ({ state with machina = Server machina }, []) 115 + 116 + let answer_client_certificate_verify state (session : session_data) sctx cctx verify raw log = 117 + let sigdata = String.concat "" log in 118 + let* () = 119 + verify_digitally_signed state.protocol_version 120 + state.config.signature_algorithms verify sigdata 121 + session.common_session_data.peer_certificate 122 + in 123 + let machina = AwaitClientChangeCipherSpec (session, sctx, cctx, log @ [raw]) in 124 + Ok ({ state with machina = Server machina }, []) 125 + 126 + let answer_client_key_exchange_RSA state (session : session_data) kex raw log = 127 + (* due to bleichenbacher attach, we should use a random pms *) 128 + (* then we do not leak any decryption or padding errors! *) 129 + let other = Writer.assemble_protocol_version state.protocol_version ^ Mirage_crypto_rng.generate 46 in 130 + let validate_premastersecret k = 131 + (* Client implementations MUST always send the correct version number in 132 + PreMasterSecret. If ClientHello.client_version is TLS 1.1 or higher, 133 + server implementations MUST check the version number as described in 134 + the note below. If the version number is TLS 1.0 or earlier, server 135 + implementations SHOULD check the version number, but MAY have a 136 + configuration option to disable the check. Note that if the check 137 + fails, the PreMasterSecret SHOULD be randomized as described below *) 138 + (* we do not provide an option to disable the version checking (yet!) *) 139 + match String.length k = 48, Reader.parse_any_version k with 140 + | true, Ok c_ver when c_ver = session.client_version -> k 141 + | _ -> other 142 + in 143 + 144 + let* k = private_key session in 145 + match k with 146 + | `RSA key -> 147 + let pms = match Mirage_crypto_pk.Rsa.PKCS1.decrypt ~key kex with 148 + | None -> validate_premastersecret other 149 + | Some k -> validate_premastersecret k 150 + in 151 + Ok (establish_master_secret state session pms raw log) 152 + | _ -> Error (`Fatal (`Bad_certificate "expected RSA certificate")) 153 + 154 + let answer_client_key_exchange_DHE state session secret kex raw log = 155 + let* pms = 156 + let open Mirage_crypto_ec in 157 + let map_ecdh_error = 158 + Result.map_error (fun e -> `Fatal (`Handshake (`BadECDH e))) 159 + in 160 + match secret with 161 + | `P256 priv -> 162 + let* share = map_reader_error (Reader.parse_client_ec_key_exchange kex) in 163 + map_ecdh_error (P256.Dh.key_exchange priv share) 164 + | `P384 priv -> 165 + let* share = map_reader_error (Reader.parse_client_ec_key_exchange kex) in 166 + map_ecdh_error (P384.Dh.key_exchange priv share) 167 + | `P521 priv -> 168 + let* share = map_reader_error (Reader.parse_client_ec_key_exchange kex) in 169 + map_ecdh_error (P521.Dh.key_exchange priv share) 170 + | `X25519 priv -> 171 + let* share = map_reader_error (Reader.parse_client_ec_key_exchange kex) in 172 + map_ecdh_error (X25519.key_exchange priv share) 173 + | `Finite_field secret -> 174 + let* share = map_reader_error (Reader.parse_client_dh_key_exchange kex) in 175 + Option.to_result 176 + ~none:(`Fatal (`Handshake (`BadDH "invalid FF"))) 177 + (Mirage_crypto_pk.Dh.shared secret share) 178 + in 179 + Ok (establish_master_secret state session pms raw log) 180 + 181 + let sig_algs (client_hello : client_hello) = 182 + Utils.map_find 183 + ~f:(function `SignatureAlgorithms xs -> Some xs | _ -> None) 184 + client_hello.extensions 185 + 186 + let ecc_group configured_groups requested_groups = 187 + Utils.first_match requested_groups configured_groups 188 + 189 + let agreed_cipher cert ecc requested = 190 + let usage_matches cipher = 191 + let csusage = 192 + Ciphersuite.(required_usage @@ ciphersuite_kex cipher) 193 + in 194 + supports_key_usage ~not_present:true csusage cert 195 + in 196 + let cciphers = List.filter usage_matches requested in 197 + if ecc then 198 + cciphers 199 + else 200 + List.filter (fun x -> not (Ciphersuite.ecdhe x)) cciphers 201 + 202 + let server_hello config (client_hello : client_hello) (session : session_data) version reneg = 203 + (* RFC 4366: server shall reply with an empty hostname extension *) 204 + let host = Option.fold ~none:[] ~some:(fun _ -> [`Hostname]) session.common_session_data.own_name 205 + and server_random = 206 + let suffix = 207 + match version, max_protocol_version config.protocol_versions with 208 + | `TLS_1_2, `TLS_1_3 -> Packet.downgrade12 209 + | _, `TLS_1_3 -> Packet.downgrade11 210 + | _ -> "" 211 + in 212 + let rst = Mirage_crypto_rng.generate (32 - String.length suffix) in 213 + rst ^ suffix 214 + and secren = match reneg with 215 + | None -> `SecureRenegotiation "" 216 + | Some (cvd, svd) -> `SecureRenegotiation (cvd ^ svd) 217 + and ems = if session.extended_ms then 218 + [`ExtendedMasterSecret] 219 + else 220 + [] 221 + and session_id = 222 + match String.length session.session_id with 223 + | 0 -> Mirage_crypto_rng.generate 32 224 + | _ -> session.session_id 225 + and alpn = 226 + match session.common_session_data.alpn_protocol with 227 + | None -> [] 228 + | Some protocol -> [`ALPN protocol] 229 + and ecpointformat = 230 + match Utils.map_find ~f:(function `ECPointFormats -> Some () | _ -> None) client_hello.extensions with 231 + | Some () when Ciphersuite.ecdhe session.ciphersuite -> [ `ECPointFormats ] 232 + | _ -> [] 233 + in 234 + let sh = ServerHello 235 + { server_version = version ; 236 + server_random = server_random ; 237 + sessionid = Some session_id ; 238 + ciphersuite = session.ciphersuite ; 239 + extensions = secren :: host @ ems @ alpn @ ecpointformat } 240 + in 241 + trace_cipher session.ciphersuite ; 242 + Tracing.debug (fun m -> m "version %a" pp_tls_version version) ; 243 + Tracing.hs ~tag:"handshake-out" sh ; 244 + let common_session_data = { session.common_session_data with server_random } in 245 + (Writer.assemble_handshake sh, 246 + { session with common_session_data ; session_id }) 247 + 248 + let answer_client_hello_common state reneg ch raw = 249 + let process_client_hello ch config = 250 + let host = hostname ch 251 + and groups = groups ch 252 + and cciphers = List.filter_map Ciphersuite.any_ciphersuite_to_ciphersuite ch.ciphersuites 253 + in 254 + let configured_ecc_groups, other_groups = List.partition Config.elliptic_curve config.groups in 255 + let ecc_group = ecc_group configured_ecc_groups groups 256 + and cciphers = List.filter (fun c -> not (Ciphersuite.ciphersuite_tls13 c)) cciphers 257 + in 258 + let cciphers = List.filter (fun c -> List.mem c config.ciphers) cciphers in 259 + let f = 260 + (* from the ciphers, figure out: 261 + - (a) RSA only (b) EC only 262 + - (c) static RSA only (keyUsage = KeyEncipherment) (d) DHE only (keyUsage = DigitalSignature) 263 + - (e) from the groups (they indicate the key type!) 264 + *) 265 + let kt_filter = 266 + match List.partition (fun c -> Ciphersuite.ciphersuite_keytype c = `RSA) cciphers with 267 + | _::_, [] -> begin fun s -> match X509.Certificate.public_key s with `RSA _ -> true | _ -> false end 268 + | [], _::_ -> begin fun s -> match X509.Certificate.public_key s with `ED25519 _ | `P256 _ | `P384 _ | `P521 _ -> true | _ -> false end 269 + | _, _ -> begin fun _s -> true end 270 + in 271 + let ku_filter = 272 + match List.partition (fun c -> Ciphersuite.ciphersuite_kex c = `RSA) cciphers with 273 + | _::_, [] -> supports_key_usage ~not_present:true `Key_encipherment 274 + | [], _::_ -> supports_key_usage ~not_present:true `Digital_signature 275 + | _ -> begin fun _ -> true end 276 + in 277 + let kt_matches_group s = 278 + match X509.Certificate.public_key s with 279 + | `RSA _ -> true 280 + | `ED25519 _ -> List.mem `X25519 groups 281 + | `P256 _ -> List.mem `P256 groups 282 + | `P384 _ -> List.mem `P384 groups 283 + | `P521 _ -> List.mem `P521 groups 284 + in 285 + fun s -> 286 + kt_filter s && ku_filter s && kt_matches_group s 287 + in 288 + let signature_algorithms = sig_algs ch in 289 + let* cciphers, chain, priv = 290 + let* r = 291 + agreed_cert ~f ?signature_algorithms config.own_certificates host 292 + in 293 + match r with 294 + | (c::cs, priv) -> 295 + let cciphers = agreed_cipher c (ecc_group <> None) cciphers in 296 + Ok (cciphers, c::cs, Some priv) 297 + | ([], _) -> Error (`Fatal (`Handshake (`Message "couldn't find certificate chain"))) 298 + in 299 + 300 + let* cipher = 301 + match Utils.first_match cciphers config.ciphers with 302 + | Some x -> Ok x 303 + | None -> 304 + let* _ = 305 + Option.to_result 306 + ~none:(`Fatal (`Handshake (`Message "no supported ciphersuite"))) 307 + (Utils.first_match cciphers Config.Ciphers.supported) 308 + in 309 + Error (`Error (`NoConfiguredCiphersuite cciphers)) 310 + in 311 + 312 + let extended_ms = List.mem `ExtendedMasterSecret ch.extensions in 313 + 314 + Log.debug (fun m -> m "cipher %a" Ciphersuite.pp_ciphersuite cipher) ; 315 + 316 + let* alpn_protocol = alpn_protocol config ch in 317 + 318 + let group = 319 + if Ciphersuite.ecdhe cipher then 320 + ecc_group 321 + else match other_groups with 322 + | [] -> None 323 + | c::_ -> Some c 324 + in 325 + let session = 326 + let session = empty_session in 327 + let common_session_data = { 328 + session.common_session_data with 329 + client_random = ch.client_random ; 330 + own_certificate = chain ; 331 + own_private_key = priv ; 332 + own_name = host ; 333 + alpn_protocol = alpn_protocol 334 + } in 335 + { session with 336 + common_session_data ; 337 + client_version = ch.client_version ; 338 + ciphersuite = cipher ; 339 + group = group ; 340 + extended_ms = extended_ms ; 341 + } 342 + in 343 + Ok session 344 + 345 + and server_cert (session : session_data) = 346 + match session.common_session_data.own_certificate with 347 + | [] -> [] 348 + | certs -> 349 + let cs = List.map X509.Certificate.encode_der certs in 350 + let cert = Certificate (Writer.assemble_certificates cs) in 351 + Tracing.hs ~tag:"handshake-out" cert ; 352 + [ Writer.assemble_handshake cert ] 353 + 354 + and cert_request version config (session : session_data) = 355 + let open Writer in 356 + match config.authenticator with 357 + | None -> Ok ([], session) 358 + | Some _ -> 359 + let cas = 360 + List.map X509.Distinguished_name.encode_der config.acceptable_cas 361 + and certs = 362 + [ Packet.RSA_SIGN ; Packet.ECDSA_SIGN ] 363 + in 364 + let* data = 365 + match version with 366 + | `TLS_1_0 | `TLS_1_1 -> 367 + Ok (assemble_certificate_request certs cas) 368 + | `TLS_1_2 -> 369 + Ok (assemble_certificate_request_1_2 certs config.signature_algorithms cas) 370 + in 371 + let certreq = CertificateRequest data in 372 + Tracing.hs ~tag:"handshake-out" certreq ; 373 + let common_session_data = { session.common_session_data with client_auth = true } in 374 + Ok ([ assemble_handshake certreq ], { session with common_session_data }) 375 + 376 + and kex_dhe config (session : session_data) version sig_algs = 377 + let* secret, written = 378 + match session.group with 379 + | None -> assert false (* can not happen *) 380 + | Some g -> 381 + let open Mirage_crypto_ec in 382 + match group_to_impl g with 383 + | `Finite_field g -> 384 + let secret, msg = Mirage_crypto_pk.Dh.gen_key g in 385 + let dh_param = Crypto.dh_params_pack g msg in 386 + let dh_params = Writer.assemble_dh_parameters dh_param in 387 + Ok (`Finite_field secret, dh_params) 388 + | `P256 -> 389 + let secret, shared = P256.Dh.gen_key () in 390 + let params = Writer.assemble_ec_parameters `P256 shared in 391 + Ok (`P256 secret, params) 392 + | `P384 -> 393 + let secret, shared = P384.Dh.gen_key () in 394 + let params = Writer.assemble_ec_parameters `P384 shared in 395 + Ok (`P384 secret, params) 396 + | `P521 -> 397 + let secret, shared = P521.Dh.gen_key () in 398 + let params = Writer.assemble_ec_parameters `P521 shared in 399 + Ok (`P521 secret, params) 400 + | `X25519 -> 401 + let secret, shared = X25519.gen_key () in 402 + let params = Writer.assemble_ec_parameters `X25519 shared in 403 + Ok (`X25519 secret, params) 404 + in 405 + let data = String.concat "" [ 406 + session.common_session_data.client_random ; 407 + session.common_session_data.server_random ; 408 + written 409 + ] 410 + in 411 + let* priv = private_key session in 412 + let* sgn = signature version data sig_algs config.signature_algorithms priv in 413 + let kex = ServerKeyExchange (written ^ sgn) in 414 + let hs = Writer.assemble_handshake kex in 415 + Tracing.hs ~tag:"handshake-out" kex ; 416 + Ok (hs, secret) 417 + in 418 + 419 + let* session = process_client_hello ch state.config in 420 + let sh, session = server_hello state.config ch session state.protocol_version reneg in 421 + let certificates = server_cert session 422 + and hello_done = Writer.assemble_handshake ServerHelloDone 423 + in 424 + let* cert_req, session = 425 + cert_request (state_version state) state.config session 426 + in 427 + 428 + let* out_recs, machina = 429 + match Ciphersuite.ciphersuite_kex session.ciphersuite with 430 + | #Ciphersuite.key_exchange_algorithm_dhe -> 431 + let* kex, dh = 432 + kex_dhe state.config session state.protocol_version (sig_algs ch) 433 + in 434 + let outs = sh :: certificates @ [ kex ] @ cert_req @ [ hello_done ] in 435 + let log = raw :: outs in 436 + let machina = 437 + if session.common_session_data.client_auth then 438 + AwaitClientCertificate_DHE (session, dh, log) 439 + else 440 + AwaitClientKeyExchange_DHE (session, dh, log) 441 + in 442 + Tracing.hs ~tag:"handshake-out" ServerHelloDone ; 443 + Ok (outs, machina) 444 + | `RSA -> 445 + let outs = sh :: certificates @ cert_req @ [ hello_done ] in 446 + let log = raw :: outs in 447 + let machina = 448 + if session.common_session_data.client_auth then 449 + AwaitClientCertificate_RSA (session, log) 450 + else 451 + AwaitClientKeyExchange_RSA (session, log) 452 + in 453 + Tracing.hs ~tag:"handshake-out" ServerHelloDone ; 454 + Ok (outs, machina) 455 + in 456 + 457 + Ok ({ state with machina = Server machina }, 458 + [`Record (Packet.HANDSHAKE, String.concat "" out_recs)]) 459 + 460 + (* TODO could benefit from result monadd *) 461 + let agreed_version supported (client_hello : client_hello) = 462 + let raw_client_versions = 463 + match List.filter_map (function `SupportedVersions vs -> Some vs | _ -> None) client_hello.extensions with 464 + | [] -> [client_hello.client_version] 465 + | [vs] -> vs 466 + | _ -> invalid_arg "bad supported version extension" 467 + in 468 + let supported_versions = List.fold_left (fun acc v -> 469 + match any_version_to_version v with 470 + | None -> acc 471 + | Some v -> v :: acc) [] raw_client_versions 472 + in 473 + let client_versions = List.sort_uniq compare_tls_version supported_versions in 474 + match 475 + List.fold_left (fun r v -> 476 + match supported_protocol_version supported v with 477 + | None -> r 478 + | Some v -> Some v) 479 + None client_versions 480 + with 481 + | Some x -> Ok x 482 + | None -> match supported_versions with 483 + | [] -> Error (`Fatal (`Protocol_version (`None_supported raw_client_versions))) 484 + | _ -> Error (`Error (`NoConfiguredVersions supported_versions)) 485 + 486 + let answer_client_hello state (ch : client_hello) raw = 487 + let ensure_reneg ciphers their_data = 488 + let reneg_cs = List.mem Packet.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ciphers in 489 + let err = `Fatal (`Handshake (`Message "invalid renegotiation")) in 490 + match reneg_cs, their_data with 491 + | _, Some x -> guard (String.length x = 0) err 492 + | true, _ -> Ok () 493 + | _ -> Error err 494 + 495 + and resume (ch : client_hello) state = 496 + let epoch_matches (epoch : Core.epoch_data) version ciphers extensions = 497 + let cciphers = List.filter_map Ciphersuite.any_ciphersuite_to_ciphersuite ciphers in 498 + List.mem epoch.ciphersuite cciphers && 499 + version = epoch.protocol_version && 500 + (not state.config.use_reneg || 501 + (List.mem `ExtendedMasterSecret extensions && epoch.extended_ms)) 502 + in 503 + 504 + match Option.bind ch.sessionid state.config.session_cache with 505 + | Some epoch when epoch_matches epoch state.protocol_version ch.ciphersuites ch.extensions -> 506 + let session = 507 + let session = session_of_epoch epoch in 508 + let common_session_data = { 509 + session.common_session_data with 510 + client_random = ch.client_random ; 511 + client_auth = (epoch.peer_certificate <> None) ; 512 + } in 513 + { session with common_session_data ; client_version = ch.client_version } 514 + in 515 + Some session 516 + | _ -> None 517 + 518 + and answer_resumption session state = 519 + let version = state_version state in 520 + let sh, session = server_hello state.config ch session version None in 521 + (* we really do not want to have any leftover handshake fragments *) 522 + let* () = 523 + guard (String.length state.hs_fragment = 0) 524 + (`Fatal (`Handshake `Fragments)) 525 + in 526 + let client_ctx, server_ctx = 527 + Handshake_crypto.initialise_crypto_ctx version session 528 + in 529 + let ccs = change_cipher_spec in 530 + let log = [ raw ; sh ] in 531 + let server = 532 + Handshake_crypto.finished 533 + version session.ciphersuite session.common_session_data.master_secret "server finished" log 534 + in 535 + let session = { session with tls_unique = server } in 536 + let fin = Finished server in 537 + let fin_raw = Writer.assemble_handshake fin in 538 + Tracing.cs ~tag:"change-cipher-spec-out" (snd ccs) ; 539 + Tracing.hs ~tag:"handshake-out" fin ; 540 + let machina = AwaitClientChangeCipherSpecResume (session, client_ctx, server, log @ [fin_raw]) in 541 + Ok ({ state with machina = Server machina }, 542 + [ `Record (Packet.HANDSHAKE, sh) ; 543 + `Record ccs ; 544 + `Change_enc server_ctx ; 545 + `Record (Packet.HANDSHAKE, fin_raw)]) 546 + in 547 + 548 + let process_client_hello config ch version = 549 + let cciphers = ch.ciphersuites in 550 + let* () = client_hello_valid version ch in 551 + let* () = 552 + guard (not (List.mem Packet.TLS_FALLBACK_SCSV cciphers) || 553 + version = max_protocol_version config.protocol_versions) 554 + (`Fatal `Inappropriate_fallback) 555 + in 556 + let theirs = get_secure_renegotiation ch.extensions in 557 + ensure_reneg cciphers theirs 558 + in 559 + 560 + let process protocol_version = 561 + let* () = process_client_hello state.config ch protocol_version in 562 + let state = { state with protocol_version } in 563 + (match resume ch state with 564 + | None -> answer_client_hello_common state None ch raw 565 + | Some session -> answer_resumption session state) 566 + in 567 + 568 + let* v = agreed_version state.config.protocol_versions ch in 569 + match v with 570 + | `TLS_1_3 -> Handshake_server13.answer_client_hello ~hrr:false state ch raw 571 + | protocol_version -> process protocol_version 572 + 573 + let answer_client_hello_reneg state (ch : client_hello) raw = 574 + (* ensure reneg allowed and supplied *) 575 + let ensure_reneg our_data their_data = 576 + let err = `Fatal (`Handshake (`Message "invalid renegotiation")) in 577 + match our_data, their_data with 578 + | (cvd, _), Some x -> guard (String.equal cvd x) err 579 + | _ -> Error err 580 + in 581 + 582 + let process_client_hello config oldversion ours ch = 583 + let* () = client_hello_valid oldversion ch in 584 + let* version = agreed_version config.protocol_versions ch in 585 + let* () = 586 + guard (version = oldversion) 587 + (`Fatal (`Handshake (`Message "invalid renegotiation version"))) 588 + in 589 + let theirs = get_secure_renegotiation ch.extensions in 590 + let* () = ensure_reneg ours theirs in 591 + Ok version 592 + in 593 + 594 + let config = state.config in 595 + match config.use_reneg, state.session with 596 + | true , `TLS session :: _ -> 597 + let reneg = session.renegotiation in 598 + let* _version = process_client_hello config state.protocol_version reneg ch in 599 + answer_client_hello_common state (Some reneg) ch raw 600 + | false, _ -> 601 + let no_reneg = Writer.assemble_alert ~level:Packet.WARNING Packet.NO_RENEGOTIATION in 602 + Tracing.debug (fun m -> m "alert-out (warning, no_renegotiation)") ; 603 + Ok (state, [`Record (Packet.ALERT, no_reneg)]) 604 + | true , _ -> Error (`Fatal (`Handshake (`Message "couldn't find an earlier session"))) 605 + 606 + let handle_change_cipher_spec ss state packet = 607 + let* () = map_reader_error (Reader.parse_change_cipher_spec packet) in 608 + match ss with 609 + | AwaitClientChangeCipherSpec (session, server_ctx, client_ctx, log) -> 610 + let* () = 611 + guard (String.length state.hs_fragment = 0) 612 + (`Fatal (`Handshake `Fragments)) 613 + in 614 + let ccs = change_cipher_spec in 615 + let machina = AwaitClientFinished (session, log) 616 + in 617 + Tracing.cs ~tag:"change-cipher-spec-in" packet ; 618 + Tracing.cs ~tag:"change-cipher-spec-out" packet ; 619 + 620 + Ok ({ state with machina = Server machina }, 621 + [`Record ccs; `Change_enc server_ctx; `Change_dec client_ctx]) 622 + | AwaitClientChangeCipherSpecResume (session, client_ctx, server_verify, log) -> 623 + let* () = 624 + guard (String.length state.hs_fragment = 0) 625 + (`Fatal (`Handshake `Fragments)) 626 + in 627 + let machina = AwaitClientFinishedResume (session, server_verify, log) 628 + in 629 + Tracing.cs ~tag:"change-cipher-spec-in" packet ; 630 + 631 + Ok ({ state with machina = Server machina }, 632 + [`Change_dec client_ctx]) 633 + | _ -> Error (`Fatal (`Unexpected (`Message "change cipher spec"))) 634 + 635 + let handle_handshake ss hs buf = 636 + let* handshake = map_reader_error (Reader.parse_handshake buf) in 637 + Tracing.hs ~tag:"handshake-in" handshake; 638 + match ss, handshake with 639 + | AwaitClientHello, ClientHello ch -> 640 + answer_client_hello hs ch buf 641 + | AwaitClientCertificate_RSA (session, log), Certificate cs -> 642 + let* cs = map_reader_error (Reader.parse_certificates cs) in 643 + answer_client_certificate_RSA hs session cs buf log 644 + | AwaitClientCertificate_DHE (session, dh_sent, log), Certificate cs -> 645 + let* cs = map_reader_error (Reader.parse_certificates cs) in 646 + answer_client_certificate_DHE hs session dh_sent cs buf log 647 + | AwaitClientKeyExchange_RSA (session, log), ClientKeyExchange cs -> 648 + let* kex = map_reader_error (Reader.parse_client_dh_key_exchange cs) in 649 + answer_client_key_exchange_RSA hs session kex buf log 650 + | AwaitClientKeyExchange_DHE (session, dh_sent, log), ClientKeyExchange kex -> 651 + answer_client_key_exchange_DHE hs session dh_sent kex buf log 652 + | AwaitClientCertificateVerify (session, sctx, cctx, log), CertificateVerify ver -> 653 + answer_client_certificate_verify hs session sctx cctx ver buf log 654 + | AwaitClientFinished (session, log), Finished fin -> 655 + answer_client_finished hs session fin buf log 656 + | AwaitClientFinishedResume (session, server_verify, log), Finished fin -> 657 + answer_client_finished_resume hs session server_verify fin buf log 658 + | Established, ClientHello ch -> (* client-initiated renegotiation *) 659 + answer_client_hello_reneg hs ch buf 660 + | AwaitClientHelloRenegotiate, ClientHello ch -> (* hello-request send, renegotiation *) 661 + answer_client_hello_reneg hs ch buf 662 + | _, hs -> Error (`Fatal (`Unexpected (`Handshake hs)))
+6
vendor/opam/tls/lib/handshake_server.mli
··· 1 + open State 2 + 3 + val hello_request : handshake_state -> (handshake_return, failure) result 4 + 5 + val handle_change_cipher_spec : server_handshake_state -> handshake_state -> string -> (handshake_return, failure) result 6 + val handle_handshake : server_handshake_state -> handshake_state -> string -> (handshake_return, failure) result
+511
vendor/opam/tls/lib/handshake_server13.ml
··· 1 + open State 2 + open Core 3 + open Handshake_common 4 + 5 + open Handshake_crypto13 6 + 7 + let answer_client_hello ~hrr state ch raw = 8 + let* () = client_hello_valid `TLS_1_3 ch in 9 + let* () = 10 + guard (not (hrr && List.mem `EarlyDataIndication ch.extensions)) 11 + (`Fatal (`Handshake (`Message "has 0RTT after hello retry request"))) 12 + in 13 + Tracing.debug (fun m -> m "version %a" pp_tls_version `TLS_1_3) ; 14 + 15 + let ciphers = 16 + List.filter_map Ciphersuite.any_ciphersuite_to_ciphersuite13 ch.ciphersuites 17 + in 18 + 19 + let* groups = 20 + let* gs = 21 + Option.to_result 22 + ~none:(`Fatal (`Missing_extension "supported group")) 23 + (Utils.map_find ~f:(function `SupportedGroups gs -> Some gs | _ -> None) ch.extensions) 24 + in 25 + Ok (List.filter_map Core.named_group_to_group gs) 26 + in 27 + 28 + let* keyshares = 29 + let* ks = 30 + Option.to_result 31 + ~none:(`Fatal (`Missing_extension "key share")) 32 + (Utils.map_find ~f:(function `KeyShare ks -> Some ks | _ -> None) ch.extensions) 33 + in 34 + List.fold_left (fun acc (g, ks) -> 35 + let* acc = acc in 36 + match Core.named_group_to_group g with 37 + | None -> Ok acc 38 + | Some g -> Ok ((g, ks) :: acc)) 39 + (Ok []) ks 40 + in 41 + 42 + let base_server_hello ?epoch cipher extensions = 43 + let ciphersuite = (cipher :> Ciphersuite.ciphersuite) in 44 + let sh = 45 + { server_version = `TLS_1_3 ; 46 + server_random = Mirage_crypto_rng.generate 32 ; 47 + sessionid = ch.sessionid ; 48 + ciphersuite ; 49 + extensions } 50 + in 51 + let session : session_data13 = 52 + let base = match epoch with None -> empty_session13 cipher | Some e -> session13_of_epoch cipher e in 53 + let common_session_data13 = { 54 + base.common_session_data13 with 55 + server_random = sh.server_random ; 56 + client_random = ch.client_random ; 57 + } in 58 + let resumed = match epoch with None -> false | Some _ -> true in 59 + { base with common_session_data13 ; ciphersuite13 = cipher ; resumed } 60 + in 61 + (sh, session) 62 + in 63 + let config = state.config in 64 + match 65 + Utils.first_match (List.map fst keyshares) config.Config.groups, 66 + Utils.first_match ciphers (Config.ciphers13 config) 67 + with 68 + | _, None -> Error (`Error (`NoConfiguredCiphersuite ciphers)) 69 + | None, Some cipher -> 70 + if hrr then 71 + (* avoid loops CH -> HRR -> CH -> HRR -> ... *) 72 + Error (`Fatal (`Handshake (`Message "hello retry request already sent, still no supported group"))) 73 + else 74 + (* no keyshare, looks whether there's a supported group ++ send back HRR *) 75 + begin match Utils.first_match groups config.Config.groups with 76 + | None -> Error (`Fatal (`Handshake (`Message "no supported group found"))) 77 + | Some group -> 78 + let cookie = 79 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 cipher)) in 80 + H.(to_raw_string (digest_string raw)) 81 + in 82 + let hrr = { retry_version = `TLS_1_3 ; ciphersuite = cipher ; sessionid = ch.sessionid ; selected_group = group ; extensions = [ `Cookie cookie ] } in 83 + let hrr_raw = Writer.assemble_handshake (HelloRetryRequest hrr) in 84 + Tracing.hs ~tag:"handshake-out" (HelloRetryRequest hrr) ; 85 + (* there is no early data anymore if HRR was sent (see 4.1.2) *) 86 + (* but the client wouldn't know until it received the HRR *) 87 + let early_data_left = if List.mem `EarlyDataIndication ch.extensions then config.Config.zero_rtt else 0l in 88 + let machina = Server13 AwaitClientHelloHRR13 in 89 + Ok ({ state with early_data_left ; machina }, 90 + `Record (Packet.HANDSHAKE, hrr_raw) :: 91 + (match ch.sessionid with 92 + | None -> [] 93 + | Some _ -> [`Record change_cipher_spec])) 94 + end 95 + | Some group, Some cipher -> 96 + Log.debug (fun m -> m "cipher %a" Ciphersuite.pp_ciphersuite cipher) ; 97 + Log.debug (fun m -> m "group %a" pp_group group) ; 98 + 99 + if not (List.mem group groups) then 100 + Error (`Fatal (`Handshake (`Message "keyshare group not in group list"))) 101 + else 102 + (* we already checked above in keyshares that group is present there *) 103 + let keyshare = 104 + snd (List.find (fun (g, _) -> g = group) keyshares) 105 + in 106 + (* DHE - full handshake *) 107 + 108 + let* log = 109 + if hrr then 110 + let* c = 111 + Option.to_result 112 + ~none:(`Fatal (`Missing_extension "cookie")) 113 + (Utils.map_find ~f:(function `Cookie c -> Some c | _ -> None) ch.extensions) 114 + in 115 + (* log is: 254 00 00 length c :: HRR *) 116 + let hash_hdr = Writer.assemble_message_hash (String.length c) in 117 + let hrr = { retry_version = `TLS_1_3 ; ciphersuite = cipher ; sessionid = ch.sessionid ; selected_group = group ; extensions = [ `Cookie c ]} in 118 + let hs_buf = Writer.assemble_handshake (HelloRetryRequest hrr) in 119 + Ok (String.concat "" [ hash_hdr ; c ; hs_buf ]) 120 + else 121 + Ok "" 122 + in 123 + 124 + let hostname = hostname ch in 125 + let hlen = 126 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 cipher)) in 127 + H.digest_size 128 + in 129 + 130 + let early_secret, epoch, exts, can_use_early_data = 131 + let secret ?(psk = String.make hlen '\x00') () = Handshake_crypto13.(derive (empty cipher) psk) in 132 + let no_resume = secret (), None, [], false in 133 + match 134 + config.Config.ticket_cache, 135 + Utils.map_find ~f:(function `PreSharedKeys ids -> Some ids | _ -> None) ch.extensions, 136 + Utils.map_find ~f:(function `PskKeyExchangeModes ms -> Some ms | _ -> None) ch.extensions 137 + with 138 + | None, _, _ | _, None, _ -> no_resume 139 + | Some _, Some _, None -> no_resume (* should this lead to an error instead? *) 140 + | Some cache, Some ids, Some ms -> 141 + if not (List.mem Packet.PSK_KE_DHE ms) then 142 + no_resume 143 + else 144 + let idx_ids = List.mapi (fun i id -> (i, id)) ids in 145 + match 146 + List.filter (fun (_, ((id, _), _)) -> 147 + match cache.Config.lookup id with None -> false | Some _ -> true) 148 + idx_ids 149 + with 150 + | [] -> 151 + Log.info (fun m -> m "found no id in psk cache") ; 152 + no_resume 153 + | (idx, ((id, obf_age), binder))::_ -> 154 + (* need to verify binder, do the obf_age computations + checking, 155 + figure out whether the id is in our psk cache, and use the resumption secret as input 156 + and Ok the idx *) 157 + let psk, old_epoch = 158 + match cache.Config.lookup id with 159 + | None -> assert false (* see above *) 160 + | Some x -> x 161 + in 162 + match Ciphersuite.(any_ciphersuite_to_ciphersuite13 (ciphersuite_to_any_ciphersuite old_epoch.ciphersuite)) with 163 + | None -> no_resume 164 + | Some c' -> 165 + if c' = cipher && 166 + match hostname, old_epoch.own_name with 167 + | None, None -> true 168 + | Some x, Some y -> Domain_name.equal x y 169 + | _ -> false 170 + then 171 + let now = cache.Config.timestamp () in 172 + let server_delta_t = Ptime.diff now psk.issued_at in 173 + let client_delta_t = 174 + match Ptime.Span.of_float_s Int32.(to_float (sub obf_age psk.obfuscation) /. 1000.) with 175 + | None -> 176 + Logs.debug (fun m -> m "client_delta is not computable, using 0") ; 177 + Ptime.Span.zero 178 + | Some x -> x 179 + in 180 + (* ensure server&client_delta_t are not too far off! *) 181 + match Ptime.Span.(to_int_s (abs (sub server_delta_t client_delta_t))) with 182 + | None -> 183 + Logs.debug (fun m -> m "s_c_delta computation lead nowhere") ; 184 + no_resume 185 + | Some s_c_delta -> 186 + if s_c_delta > 10 then begin 187 + Logs.debug (fun m -> m "delta between client and server is %d seconds, ignoring this ticket!" s_c_delta); 188 + no_resume 189 + end else 190 + (* if ticket_creation ts + lifetime > now, continue *) 191 + let until = match Ptime.add_span psk.issued_at (Ptime.Span.of_int_s (Int32.to_int cache.Config.lifetime)) with 192 + | None -> Ptime.epoch 193 + | Some ts -> ts 194 + in 195 + if Ptime.is_earlier now ~than:until then 196 + let early_secret = secret ~psk:psk.secret () in 197 + let binder_key = Handshake_crypto13.derive_secret early_secret "res binder" "" in 198 + let binders_len = binders_len ids in 199 + let ch_part = String.(sub raw 0 (length raw - binders_len)) in 200 + let log = log ^ ch_part in 201 + let binder' = Handshake_crypto13.finished early_secret.hash binder_key log in 202 + if String.equal binder binder' then begin 203 + (* from 4.1.2 - earlydata is not allowed after hrr *) 204 + let zero = idx = 0 && not hrr && List.mem `EarlyDataIndication ch.extensions in 205 + early_secret, Some old_epoch, [ `PreSharedKey idx ], zero 206 + end else 207 + no_resume 208 + else 209 + no_resume 210 + else 211 + no_resume 212 + in 213 + 214 + let _, early_traffic_ctx = Handshake_crypto13.early_traffic early_secret raw in 215 + 216 + let secret, public = Handshake_crypto13.dh_gen_key group in 217 + let* es = Handshake_crypto13.dh_shared secret keyshare in 218 + let hs_secret = Handshake_crypto13.derive early_secret es in 219 + Tracing.cs ~tag:"hs secret" hs_secret.secret ; 220 + 221 + let sh, session = base_server_hello ?epoch cipher (`KeyShare (group, public) :: exts) in 222 + let sh_raw = Writer.assemble_handshake (ServerHello sh) in 223 + Tracing.hs ~tag:"handshake-out" (ServerHello sh) ; 224 + 225 + let log = log ^ raw ^ sh_raw in 226 + let server_hs_secret, server_ctx, client_hs_secret, client_ctx = hs_ctx hs_secret log in 227 + 228 + let* sigalgs = 229 + Option.to_result 230 + ~none:(`Fatal (`Missing_extension "signature algorithms")) 231 + (Utils.map_find ~f:(function `SignatureAlgorithms sa -> Some sa | _ -> None) ch.extensions) 232 + in 233 + (* TODO respect certificate_signature_algs if present *) 234 + 235 + let f = supports_key_usage ~not_present:true `Digital_signature in 236 + let* chain, priv = 237 + let* r = agreed_cert ~f ~signature_algorithms:sigalgs config.Config.own_certificates hostname in 238 + match r with 239 + | c::cs, priv -> Ok (c::cs, priv) 240 + | _ -> Error (`Fatal (`Handshake (`Message "couldn't find certificate chain"))) 241 + in 242 + let* alpn_protocol = alpn_protocol config ch in 243 + let session = 244 + let common_session_data13 = { session.common_session_data13 with 245 + own_name = hostname ; own_certificate = chain ; 246 + own_private_key = Some priv ; alpn_protocol } 247 + in 248 + { session with common_session_data13 } 249 + in 250 + 251 + let ee = 252 + let hostname_ext = Option.fold ~none:[] ~some:(fun _ -> [`Hostname]) hostname 253 + and alpn = Option.fold ~none:[] ~some:(fun proto -> [`ALPN proto]) alpn_protocol 254 + and early_data = if can_use_early_data && config.Config.zero_rtt <> 0l then [ `EarlyDataIndication ] else [] 255 + in 256 + EncryptedExtensions (hostname_ext @ alpn @ early_data) 257 + in 258 + (* TODO also max_fragment_length ; client_certificate_url ; trusted_ca_keys ; user_mapping ; client_authz ; server_authz ; cert_type ; use_srtp ; heartbeat ; alpn ; status_request_v2 ; signed_cert_timestamp ; client_cert_type ; server_cert_type *) 259 + let ee_raw = Writer.assemble_handshake ee in 260 + Tracing.hs ~tag:"handshake-out" ee ; 261 + let log = log ^ ee_raw in 262 + 263 + let* c_out, log, session' = 264 + if session.resumed then 265 + Ok ([], log, session) 266 + else 267 + let out, log, session = match config.Config.authenticator with 268 + | None -> [], log, session 269 + | Some _ -> 270 + let certreq = 271 + let exts = 272 + `SignatureAlgorithms config.Config.signature_algorithms :: 273 + (match config.Config.acceptable_cas with 274 + | [] -> [] 275 + | cas -> [ `CertificateAuthorities cas ]) 276 + in 277 + CertificateRequest (Writer.assemble_certificate_request_1_3 exts) 278 + in 279 + Tracing.hs ~tag:"handshake-out" certreq ; 280 + let raw_cert_req = Writer.assemble_handshake certreq in 281 + let common_session_data13 = { session.common_session_data13 with client_auth = true } in 282 + [raw_cert_req], log ^ raw_cert_req, { session with common_session_data13 } 283 + in 284 + 285 + let certs = List.map X509.Certificate.encode_der chain in 286 + let cert = Certificate (Writer.assemble_certificates_1_3 "" certs) in 287 + let cert_raw = Writer.assemble_handshake cert in 288 + Tracing.hs ~tag:"handshake-out" cert ; 289 + let log = log ^ cert_raw in 290 + 291 + let tbs = 292 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 cipher)) in 293 + H.(to_raw_string (digest_string log)) 294 + in 295 + let* signed = 296 + signature `TLS_1_3 297 + ~context_string:"TLS 1.3, server CertificateVerify" 298 + tbs (Some sigalgs) config.Config.signature_algorithms priv 299 + in 300 + let cv = CertificateVerify signed in 301 + let cv_raw = Writer.assemble_handshake cv in 302 + Tracing.hs ~tag:"handshake-out" cv ; 303 + let log = log ^ cv_raw in 304 + Ok (out @ [cert_raw; cv_raw], log, session) 305 + in 306 + 307 + let master_secret = Handshake_crypto13.derive hs_secret (String.make hlen '\x00') in 308 + Tracing.cs ~tag:"master-secret" master_secret.secret ; 309 + 310 + let f_data = finished hs_secret.hash server_hs_secret log in 311 + let fin = Finished f_data in 312 + let fin_raw = Writer.assemble_handshake fin in 313 + 314 + Tracing.hs ~tag:"handshake-out" fin ; 315 + 316 + let log = log ^ fin_raw in 317 + let server_app_secret, server_app_ctx, client_app_secret, client_app_ctx = 318 + app_ctx master_secret log 319 + in 320 + let exporter_master_secret = Handshake_crypto13.exporter master_secret log in 321 + let session' = { session' with server_app_secret ; client_app_secret ; exporter_master_secret } in 322 + 323 + let* () = 324 + guard (String.length state.hs_fragment = 0) 325 + (`Fatal (`Handshake `Fragments)) 326 + in 327 + 328 + (* send sessionticket early *) 329 + (* TODO track the nonce across handshakes / newsessionticket messages (i.e. after post-handshake auth) - needs to be unique! *) 330 + let st, st_raw = 331 + match session.resumed, config.Config.ticket_cache with 332 + | true, _ | _, None -> None, [] 333 + | false, Some cache -> 334 + let age_add = 335 + let cs = Mirage_crypto_rng.generate 4 in 336 + String.get_int32_be cs 0 337 + in 338 + let psk_id = Mirage_crypto_rng.generate 32 in 339 + let nonce = Mirage_crypto_rng.generate 4 in 340 + let extensions = match config.Config.zero_rtt with 341 + | 0l -> [] 342 + | x -> [ `EarlyDataIndication x ] 343 + in 344 + let st = { lifetime = cache.Config.lifetime ; age_add ; nonce ; ticket = psk_id ; extensions } in 345 + Tracing.hs ~tag:"handshake-out" (SessionTicket st) ; 346 + let st_raw = Writer.assemble_handshake (SessionTicket st) in 347 + (Some st, [st_raw]) 348 + in 349 + 350 + let session = 351 + let common_session_data13 = { session'.common_session_data13 with master_secret = master_secret.secret } in 352 + { session' with common_session_data13 ; master_secret } 353 + in 354 + let st, session = 355 + if can_use_early_data then 356 + (AwaitEndOfEarlyData13 (client_hs_secret, client_ctx, client_app_ctx, st, log), 357 + `TLS13 { session with state = `ZeroRTT } :: state.session) 358 + else if session.common_session_data13.client_auth then 359 + (AwaitClientCertificate13 (session, client_hs_secret, client_app_ctx, st, log), 360 + state.session) 361 + else 362 + (AwaitClientFinished13 (client_hs_secret, client_app_ctx, st, log), 363 + `TLS13 session :: state.session) 364 + in 365 + let early_data_left = if List.mem `EarlyDataIndication ch.extensions then config.Config.zero_rtt else 0l in 366 + Ok ({ state with machina = Server13 st ; session ; early_data_left }, 367 + `Record (Packet.HANDSHAKE, sh_raw) :: 368 + (match ch.sessionid with 369 + | Some _ when not hrr -> [`Record change_cipher_spec] 370 + | _ -> []) @ 371 + [ `Change_enc server_ctx ; 372 + `Change_dec (if can_use_early_data then early_traffic_ctx else client_ctx) ; 373 + `Record (Packet.HANDSHAKE, ee_raw) ] @ 374 + List.map (fun data -> `Record (Packet.HANDSHAKE, data)) c_out @ 375 + [ `Record (Packet.HANDSHAKE, fin_raw) ; 376 + `Change_enc server_app_ctx ] @ 377 + List.map (fun data -> `Record (Packet.HANDSHAKE, data)) st_raw) 378 + 379 + let answer_client_certificate state cert (sd : session_data13) client_fini dec_ctx st raw log = 380 + let* c = map_reader_error (Reader.parse_certificates_1_3 cert) in 381 + match c, state.config.Config.authenticator with 382 + | (_, []), None -> Error (`Fatal (`Handshake (`Message "couldn't find authenticator"))) 383 + | (_ctx, []), Some auth -> 384 + begin match auth ~host:None [] with 385 + | Ok anchor -> 386 + let trust_anchor = match anchor with 387 + | None -> None 388 + | Some (_chain, ta) -> Some ta 389 + in 390 + let common_session_data13 = { sd.common_session_data13 with trust_anchor } in 391 + let sd = { sd with common_session_data13 } in 392 + let st = AwaitClientFinished13 (client_fini, dec_ctx, st, log ^ raw) in 393 + Ok ({ state with machina = Server13 st ; session = `TLS13 sd :: state.session }, []) 394 + | Error e -> Error (`Error (`AuthenticationFailure e)) 395 + end 396 + | (_ctx, cert_exts), auth -> 397 + (* TODO what to do with ctx? send through authenticator? *) 398 + (* TODO what to do with extensions? *) 399 + let certs = List.map fst cert_exts in 400 + let* peer_certificate, received_certificates, peer_certificate_chain, trust_anchor = 401 + validate_chain auth certs state.config.Config.ip None 402 + in 403 + let sd' = let common_session_data13 = { 404 + sd.common_session_data13 with 405 + received_certificates ; 406 + peer_certificate ; 407 + peer_certificate_chain ; 408 + trust_anchor 409 + } in 410 + { sd with common_session_data13 } 411 + in 412 + let st = AwaitClientCertificateVerify13 (sd', client_fini, dec_ctx, st, log ^ raw) in 413 + Ok ({ state with machina = Server13 st }, []) 414 + 415 + let answer_client_certificate_verify state cv (sd : session_data13) client_fini dec_ctx st raw log = 416 + let tbs = 417 + let module H = (val Digestif.module_of_hash' (Ciphersuite.hash13 sd.ciphersuite13)) in 418 + H.(to_raw_string (digest_string log)) 419 + in 420 + let* () = 421 + verify_digitally_signed `TLS_1_3 422 + ~context_string:"TLS 1.3, client CertificateVerify" 423 + state.config.Config.signature_algorithms cv tbs 424 + sd.common_session_data13.peer_certificate 425 + in 426 + let st = AwaitClientFinished13 (client_fini, dec_ctx, st, log ^ raw) in 427 + Ok ({ state with machina = Server13 st ; session = `TLS13 sd :: state.session }, []) 428 + 429 + let answer_client_finished state fin client_fini dec_ctx st raw log = 430 + match state.session with 431 + | `TLS13 session :: rest -> 432 + let hash = Ciphersuite.hash13 session.ciphersuite13 in 433 + let data = finished hash client_fini log in 434 + let* () = 435 + guard (String.equal data fin) 436 + (`Fatal (`Handshake (`Message "couldn't verify finished"))) 437 + in 438 + let* () = 439 + guard (String.length state.hs_fragment = 0) 440 + (`Fatal (`Handshake `Fragments)) 441 + in 442 + let session' = match st, state.config.Config.ticket_cache with 443 + | None, _ | _, None -> session 444 + | Some st, Some cache -> 445 + let resumption_secret = Handshake_crypto13.resumption session.master_secret (log ^ raw) in 446 + let session = { session with resumption_secret } in 447 + let secret = Handshake_crypto13.res_secret hash resumption_secret st.nonce in 448 + let issued_at = cache.Config.timestamp () in 449 + let psk = { identifier = st.ticket ; obfuscation = st.age_add ; secret ; lifetime = st.lifetime ; early_data = state.config.Config.zero_rtt ; issued_at } in 450 + let epoch = epoch_of_session true None `TLS_1_3 (`TLS13 session) in 451 + cache.Config.ticket_granted psk epoch ; 452 + session 453 + in 454 + let state' = { state with machina = Server13 Established13 ; session = `TLS13 session' :: rest } in 455 + Ok (state', [ `Change_dec dec_ctx ]) 456 + | _ -> Error (`Fatal (`Handshake (`Message "no session found in finished"))) 457 + 458 + let handle_end_of_early_data state cf hs_ctx cc st buf log = 459 + let machina = AwaitClientFinished13 (cf, cc, st, log ^ buf) in 460 + match state.session with 461 + | `TLS13 s1 :: _ -> 462 + let session = `TLS13 { s1 with state = `Established } :: state.session in 463 + Ok ({ state with machina = Server13 machina ; session }, [ `Change_dec hs_ctx ]) 464 + | _ -> 465 + Error (`Fatal (`Handshake (`Message "no session handling end of early data"))) 466 + 467 + let handle_key_update state req = 468 + match state.session with 469 + | `TLS13 session :: _ -> 470 + let* () = 471 + guard (String.length state.hs_fragment = 0) 472 + (`Fatal (`Handshake `Fragments)) 473 + in 474 + let client_app_secret, client_ctx = 475 + app_secret_n_1 session.master_secret session.client_app_secret 476 + in 477 + let session' = { session with client_app_secret } in 478 + let session', out = match req with 479 + | Packet.UPDATE_NOT_REQUESTED -> session', [] 480 + | Packet.UPDATE_REQUESTED -> 481 + let server_app_secret, server_ctx = 482 + app_secret_n_1 session.master_secret session.server_app_secret 483 + in 484 + let ku = KeyUpdate Packet.UPDATE_NOT_REQUESTED in 485 + Tracing.hs ~tag:"handshake-out" ku ; 486 + let ku_raw = Writer.assemble_handshake ku in 487 + { session' with server_app_secret }, 488 + [ `Record (Packet.HANDSHAKE, ku_raw); `Change_enc server_ctx ] 489 + in 490 + let session = `TLS13 session' :: state.session in 491 + let state' = { state with machina = Server13 Established13 ; session } in 492 + Ok (state', `Change_dec client_ctx :: out) 493 + | _ -> Error (`Fatal (`Handshake (`Message "no session while handling key update"))) 494 + 495 + let handle_handshake cs hs buf = 496 + let* handshake = map_reader_error (Reader.parse_handshake buf) in 497 + Tracing.hs ~tag:"handshake-in" handshake; 498 + match cs, handshake with 499 + | AwaitClientHelloHRR13, ClientHello ch -> 500 + answer_client_hello ~hrr:true hs ch buf 501 + | AwaitClientCertificate13 (sd, cf, cc, st, log), Certificate cert -> 502 + answer_client_certificate hs cert sd cf cc st buf log 503 + | AwaitClientCertificateVerify13 (sd, cf, cc, st, log), CertificateVerify cv -> 504 + answer_client_certificate_verify hs cv sd cf cc st buf log 505 + | AwaitClientFinished13 (cf, cc, st, log), Finished x -> 506 + answer_client_finished hs x cf cc st buf log 507 + | AwaitEndOfEarlyData13 (cf, hs_c, cc, st, log), EndOfEarlyData -> 508 + handle_end_of_early_data hs cf hs_c cc st buf log 509 + | Established13, KeyUpdate req -> 510 + handle_key_update hs req 511 + | _, hs -> Error (`Fatal (`Unexpected (`Handshake hs)))
+621
vendor/opam/tls/lib/packet.ml
··· 1 + (** Magic numbers of the TLS protocol. *) 2 + 3 + (* HACK: 24 bits type not in cstruct *) 4 + let get_uint24_len ~off buf = 5 + (String.get_uint16_be buf off) * 0x100 + (String.get_uint8 buf (off + 2)) 6 + 7 + let set_uint24_len ~off buf num = 8 + Bytes.set_uint16_be buf off (num / 0x100); 9 + Bytes.set_uint8 buf (off + 2) (num mod 0x100) 10 + 11 + (* TLS record content type *) 12 + type content_type = 13 + | CHANGE_CIPHER_SPEC 14 + | ALERT 15 + | HANDSHAKE 16 + | APPLICATION_DATA 17 + 18 + let content_type_to_int = function 19 + | CHANGE_CIPHER_SPEC -> 20 20 + | ALERT -> 21 21 + | HANDSHAKE -> 22 22 + | APPLICATION_DATA -> 23 23 + and int_to_content_type = function 24 + | 20 -> Some CHANGE_CIPHER_SPEC 25 + | 21 -> Some ALERT 26 + | 22 -> Some HANDSHAKE 27 + | 23 -> Some APPLICATION_DATA 28 + | _ -> None 29 + 30 + let content_type_to_string = function 31 + | CHANGE_CIPHER_SPEC -> "change cipher spec" 32 + | ALERT -> "alert" 33 + | HANDSHAKE -> "handshake" 34 + | APPLICATION_DATA -> "application data" 35 + 36 + let pp_content_type ppf ct = 37 + Fmt.string ppf (content_type_to_string ct) 38 + 39 + (* TLS alert level *) 40 + type alert_level = 41 + | WARNING 42 + | FATAL 43 + 44 + let pp_alert_level ppf = function 45 + | WARNING -> Fmt.string ppf "warning" 46 + | FATAL -> Fmt.string ppf "fatal" 47 + 48 + let alert_level_to_int = function 49 + | WARNING -> 1 50 + | FATAL -> 2 51 + and int_to_alert_level = function 52 + | 1 -> Some WARNING 53 + | 2 -> Some FATAL 54 + | _ -> None 55 + 56 + (* TLS alert types *) 57 + type alert_type = 58 + | CLOSE_NOTIFY [@id 0] (*RFC5246*) 59 + | UNEXPECTED_MESSAGE [@id 10] (*RFC5246*) 60 + | BAD_RECORD_MAC [@id 20] (*RFC5246*) 61 + | RECORD_OVERFLOW [@id 22] (*RFC5246*) 62 + | HANDSHAKE_FAILURE [@id 40] (*RFC5246*) 63 + | BAD_CERTIFICATE [@id 42] (*RFC5246*) 64 + | CERTIFICATE_EXPIRED [@id 45] (*RFC5246*) 65 + | CERTIFICATE_UNKNOWN [@id 46] (*RFC5246*) 66 + | DECODE_ERROR [@id 50] (*RFC5246*) 67 + | PROTOCOL_VERSION [@id 70] (*RFC5246*) 68 + | INAPPROPRIATE_FALLBACK [@id 86] (*draft-ietf-tls-downgrade-scsv*) 69 + | USER_CANCELED [@id 90] (*RFC5246*) 70 + | NO_RENEGOTIATION [@id 100] (*RFC5246*) 71 + | MISSING_EXTENSION [@id 109] (*RFC8446*) 72 + | UNSUPPORTED_EXTENSION [@id 110] (*RFC5246*) 73 + | UNRECOGNIZED_NAME [@id 112] (*RFC6066*) 74 + | NO_APPLICATION_PROTOCOL [@id 120] (*RFC7301*) 75 + | UNKNOWN of int 76 + 77 + let alert_type_to_string = function 78 + | CLOSE_NOTIFY -> "close notify" 79 + | UNEXPECTED_MESSAGE -> "unexpected message" 80 + | BAD_RECORD_MAC -> "bad record mac" 81 + | RECORD_OVERFLOW -> "record overflow" 82 + | HANDSHAKE_FAILURE -> "handshake failure" 83 + | BAD_CERTIFICATE -> "bad certificate" 84 + | CERTIFICATE_EXPIRED -> "certificate expired" 85 + | CERTIFICATE_UNKNOWN -> "certificate unknown" 86 + | DECODE_ERROR -> "decode error" 87 + | PROTOCOL_VERSION -> "protocol version" 88 + | INAPPROPRIATE_FALLBACK -> "inappropriate fallback" 89 + | USER_CANCELED -> "user canceled" 90 + | NO_RENEGOTIATION -> "no renegotiation" 91 + | MISSING_EXTENSION -> "missing extension" 92 + | UNSUPPORTED_EXTENSION -> "unsupported extension" 93 + | UNRECOGNIZED_NAME -> "unrecognized name" 94 + | NO_APPLICATION_PROTOCOL -> "no application protocol" 95 + | UNKNOWN x -> "unknown " ^ string_of_int x 96 + 97 + let alert_type_to_int = function 98 + | CLOSE_NOTIFY -> 0 (*RFC5246*) 99 + | UNEXPECTED_MESSAGE -> 10 (*RFC5246*) 100 + | BAD_RECORD_MAC -> 20 (*RFC5246*) 101 + | RECORD_OVERFLOW -> 22 (*RFC5246*) 102 + | HANDSHAKE_FAILURE -> 40 (*RFC5246*) 103 + | BAD_CERTIFICATE -> 42 (*RFC5246*) 104 + | CERTIFICATE_EXPIRED -> 45 (*RFC5246*) 105 + | CERTIFICATE_UNKNOWN -> 46 (*RFC5246*) 106 + | DECODE_ERROR -> 50 (*RFC5246*) 107 + | PROTOCOL_VERSION -> 70 (*RFC5246*) 108 + | INAPPROPRIATE_FALLBACK -> 86 (*draft-ietf-tls-downgrade-scsv*) 109 + | USER_CANCELED -> 90 (*RFC5246*) 110 + | NO_RENEGOTIATION -> 100 (*RFC5246*) 111 + | MISSING_EXTENSION -> 109 (*RFC8446*) 112 + | UNSUPPORTED_EXTENSION -> 110 (*RFC5246*) 113 + | UNRECOGNIZED_NAME -> 112 (*RFC6066*) 114 + | NO_APPLICATION_PROTOCOL -> 120 (*RFC7301*) 115 + | UNKNOWN x -> x 116 + and int_to_alert_type = function 117 + | 0 -> CLOSE_NOTIFY 118 + | 10 -> UNEXPECTED_MESSAGE 119 + | 20 -> BAD_RECORD_MAC 120 + | 22 -> RECORD_OVERFLOW 121 + | 40 -> HANDSHAKE_FAILURE 122 + | 42 -> BAD_CERTIFICATE 123 + | 45 -> CERTIFICATE_EXPIRED 124 + | 46 -> CERTIFICATE_UNKNOWN 125 + | 50 -> DECODE_ERROR 126 + | 70 -> PROTOCOL_VERSION 127 + | 86 -> INAPPROPRIATE_FALLBACK 128 + | 90 -> USER_CANCELED 129 + | 100 -> NO_RENEGOTIATION 130 + | 109 -> MISSING_EXTENSION 131 + | 110 -> UNSUPPORTED_EXTENSION 132 + | 112 -> UNRECOGNIZED_NAME 133 + | 120 -> NO_APPLICATION_PROTOCOL 134 + | x -> UNKNOWN x 135 + 136 + let pp_alert ppf (lvl, typ) = 137 + Fmt.pf ppf "ALERT %a %s" pp_alert_level lvl (alert_type_to_string typ) 138 + 139 + (* TLS handshake type *) 140 + type handshake_type = 141 + | HELLO_REQUEST [@id 0] 142 + | CLIENT_HELLO [@id 1] 143 + | SERVER_HELLO [@id 2] 144 + | HELLO_VERIFY_REQUEST [@id 3] (*RFC6347*) 145 + | SESSION_TICKET [@id 4] (*RFC4507, RFC8446*) 146 + | END_OF_EARLY_DATA [@id 5] (*RFC8446*) 147 + | ENCRYPTED_EXTENSIONS [@id 8] (*RFC8446*) 148 + | CERTIFICATE [@id 11] 149 + | SERVER_KEY_EXCHANGE [@id 12] 150 + | CERTIFICATE_REQUEST [@id 13] 151 + | SERVER_HELLO_DONE [@id 14] 152 + | CERTIFICATE_VERIFY [@id 15] 153 + | CLIENT_KEY_EXCHANGE [@id 16] 154 + | FINISHED [@id 20] 155 + | CERTIFICATE_URL [@id 21] (*RFC4366*) 156 + | CERTIFICATE_STATUS [@id 22] (*RFC4366*) 157 + | SUPPLEMENTAL_DATA [@id 23] (*RFC4680*) 158 + | KEY_UPDATE [@id 24] (*RFC8446*) 159 + | MESSAGE_HASH [@id 254] (*RFC8446*) 160 + 161 + let handshake_type_to_int = function 162 + | HELLO_REQUEST -> 0 163 + | CLIENT_HELLO -> 1 164 + | SERVER_HELLO -> 2 165 + | HELLO_VERIFY_REQUEST -> 3 (*RFC6347*) 166 + | SESSION_TICKET -> 4 (*RFC4507, RFC8446*) 167 + | END_OF_EARLY_DATA -> 5 (*RFC8446*) 168 + | ENCRYPTED_EXTENSIONS -> 8 (*RFC8446*) 169 + | CERTIFICATE -> 11 170 + | SERVER_KEY_EXCHANGE -> 12 171 + | CERTIFICATE_REQUEST -> 13 172 + | SERVER_HELLO_DONE -> 14 173 + | CERTIFICATE_VERIFY -> 15 174 + | CLIENT_KEY_EXCHANGE -> 16 175 + | FINISHED -> 20 176 + | CERTIFICATE_URL -> 21 (*RFC4366*) 177 + | CERTIFICATE_STATUS -> 22 (*RFC4366*) 178 + | SUPPLEMENTAL_DATA -> 23 (*RFC4680*) 179 + | KEY_UPDATE -> 24 (*RFC8446*) 180 + | MESSAGE_HASH -> 254 (*RFC8446*) 181 + and int_to_handshake_type = function 182 + | 0 -> Some HELLO_REQUEST 183 + | 1 -> Some CLIENT_HELLO 184 + | 2 -> Some SERVER_HELLO 185 + | 3 -> Some HELLO_VERIFY_REQUEST 186 + | 4 -> Some SESSION_TICKET 187 + | 5 -> Some END_OF_EARLY_DATA 188 + | 8 -> Some ENCRYPTED_EXTENSIONS 189 + | 11 -> Some CERTIFICATE 190 + | 12 -> Some SERVER_KEY_EXCHANGE 191 + | 13 -> Some CERTIFICATE_REQUEST 192 + | 14 -> Some SERVER_HELLO_DONE 193 + | 15 -> Some CERTIFICATE_VERIFY 194 + | 16 -> Some CLIENT_KEY_EXCHANGE 195 + | 20 -> Some FINISHED 196 + | 21 -> Some CERTIFICATE_URL 197 + | 22 -> Some CERTIFICATE_STATUS 198 + | 23 -> Some SUPPLEMENTAL_DATA 199 + | 24 -> Some KEY_UPDATE 200 + | 254 -> Some MESSAGE_HASH 201 + | _ -> None 202 + 203 + (* TLS certificate types *) 204 + type client_certificate_type = 205 + | RSA_SIGN [@id 1] (*RFC5246*) 206 + | ECDSA_SIGN [@id 64] (*RFC4492*) 207 + 208 + let client_certificate_type_to_int = function 209 + | RSA_SIGN -> 1 (*RFC5246*) 210 + | ECDSA_SIGN -> 64 (*RFC4492*) 211 + and int_to_client_certificate_type = function 212 + | 1 -> Some RSA_SIGN 213 + | 64 -> Some ECDSA_SIGN 214 + | _ -> None 215 + 216 + (* TLS compression methods, used in hello packets *) 217 + type compression_method = 218 + | NULL [@id 0] 219 + 220 + let compression_method_to_int = function 221 + | NULL -> 0 222 + and int_to_compression_method = function 223 + | 0 -> Some NULL 224 + | _ -> None 225 + 226 + (* TLS extensions in hello packets from RFC 6066, formerly RFC 4366 *) 227 + type extension_type = 228 + | SERVER_NAME [@id 0] 229 + | MAX_FRAGMENT_LENGTH [@id 1] 230 + | SUPPORTED_GROUPS [@id 10] (*RFC4492, RFC8446*) 231 + | EC_POINT_FORMATS [@id 11] (*RFC4492*) 232 + | SIGNATURE_ALGORITHMS [@id 13] (*RFC5246*) 233 + | APPLICATION_LAYER_PROTOCOL_NEGOTIATION [@id 16] (*RFC7301*) 234 + | PADDING [@id 21] (*RFC7685*) 235 + | EXTENDED_MASTER_SECRET [@id 23] (*RFC7627*) 236 + | SESSION_TICKET [@id 35] (*RFC4507*) 237 + | PRE_SHARED_KEY [@id 41] (*RFC8446*) 238 + | EARLY_DATA [@id 42] (*RFC8446*) 239 + | SUPPORTED_VERSIONS [@id 43] (*RFC8446*) 240 + | COOKIE [@id 44] (*RFC8446*) 241 + | PSK_KEY_EXCHANGE_MODES [@id 45] (*RFC8446*) 242 + | CERTIFICATE_AUTHORITIES [@id 47] (*RFC8446*) 243 + | POST_HANDSHAKE_AUTH [@id 49] (*RFC8446*) 244 + | KEY_SHARE [@id 51] (*RFC8446*) 245 + | RENEGOTIATION_INFO [@id 0xFF01] (*RFC5746*) 246 + 247 + let extension_type_to_int = function 248 + | SERVER_NAME -> 0 249 + | MAX_FRAGMENT_LENGTH -> 1 250 + | SUPPORTED_GROUPS -> 10 (*RFC4492, RFC8446*) 251 + | EC_POINT_FORMATS -> 11 (*RFC4492*) 252 + | SIGNATURE_ALGORITHMS -> 13 (*RFC5246*) 253 + | APPLICATION_LAYER_PROTOCOL_NEGOTIATION -> 16 (*RFC7301*) 254 + | PADDING -> 21 (*RFC7685*) 255 + | EXTENDED_MASTER_SECRET -> 23 (*RFC7627*) 256 + | SESSION_TICKET -> 35 (*RFC4507*) 257 + | PRE_SHARED_KEY -> 41 (*RFC8446*) 258 + | EARLY_DATA -> 42 (*RFC8446*) 259 + | SUPPORTED_VERSIONS -> 43 (*RFC8446*) 260 + | COOKIE -> 44 (*RFC8446*) 261 + | PSK_KEY_EXCHANGE_MODES -> 45 (*RFC8446*) 262 + | CERTIFICATE_AUTHORITIES -> 47 (*RFC8446*) 263 + | POST_HANDSHAKE_AUTH -> 49 (*RFC8446*) 264 + | KEY_SHARE -> 51 (*RFC8446*) 265 + | RENEGOTIATION_INFO -> 0xFF01 (*RFC5746*) 266 + and int_to_extension_type = function 267 + | 0 -> Some SERVER_NAME 268 + | 1 -> Some MAX_FRAGMENT_LENGTH 269 + | 10 -> Some SUPPORTED_GROUPS 270 + | 11 -> Some EC_POINT_FORMATS 271 + | 13 -> Some SIGNATURE_ALGORITHMS 272 + | 16 -> Some APPLICATION_LAYER_PROTOCOL_NEGOTIATION 273 + | 21 -> Some PADDING 274 + | 23 -> Some EXTENDED_MASTER_SECRET 275 + | 35 -> Some SESSION_TICKET 276 + | 41 -> Some PRE_SHARED_KEY 277 + | 42 -> Some EARLY_DATA 278 + | 43 -> Some SUPPORTED_VERSIONS 279 + | 44 -> Some COOKIE 280 + | 45 -> Some PSK_KEY_EXCHANGE_MODES 281 + | 47 -> Some CERTIFICATE_AUTHORITIES 282 + | 49 -> Some POST_HANDSHAKE_AUTH 283 + | 51 -> Some KEY_SHARE 284 + | 0xFF01 -> Some RENEGOTIATION_INFO 285 + | _ -> None 286 + 287 + let extension_type_to_string et = string_of_int (extension_type_to_int et) 288 + 289 + (* TLS maximum fragment length *) 290 + type max_fragment_length = 291 + | TWO_9 [@id 1] 292 + | TWO_10 [@id 2] 293 + | TWO_11 [@id 3] 294 + | TWO_12 [@id 4] 295 + 296 + let max_fragment_length_to_int = function 297 + | TWO_9 -> 1 298 + | TWO_10 -> 2 299 + | TWO_11 -> 3 300 + | TWO_12 -> 4 301 + and int_to_max_fragment_length = function 302 + | 1 -> Some TWO_9 303 + | 2 -> Some TWO_10 304 + | 3 -> Some TWO_11 305 + | 4 -> Some TWO_12 306 + | _ -> None 307 + 308 + (* TLS 1.3 pre-shared key mode (4.2.9) *) 309 + type psk_key_exchange_mode = 310 + | PSK_KE [@id 0] 311 + | PSK_KE_DHE [@id 1] 312 + 313 + let psk_key_exchange_mode_to_int = function 314 + | PSK_KE -> 0 315 + | PSK_KE_DHE -> 1 316 + and int_to_psk_key_exchange_mode = function 317 + | 0 -> Some PSK_KE 318 + | 1 -> Some PSK_KE_DHE 319 + | _ -> None 320 + 321 + (* TLS 1.3 4.2.3 *) 322 + type signature_alg = 323 + | RSA_PKCS1_MD5 [@id 0x0101] (* deprecated, TLS 1.2 only *) 324 + | RSA_PKCS1_SHA1 [@id 0x0201] (* deprecated, TLS 1.2 only *) 325 + | RSA_PKCS1_SHA224 [@id 0x0301] 326 + | RSA_PKCS1_SHA256 [@id 0x0401] 327 + | RSA_PKCS1_SHA384 [@id 0x0501] 328 + | RSA_PKCS1_SHA512 [@id 0x0601] 329 + | ECDSA_SECP256R1_SHA1 [@id 0x0203] (* deprecated, TLS 1.2 only *) 330 + | ECDSA_SECP256R1_SHA256 [@id 0x0403] 331 + | ECDSA_SECP384R1_SHA384 [@id 0x0503] 332 + | ECDSA_SECP521R1_SHA512 [@id 0x0603] 333 + | RSA_PSS_RSAENC_SHA256 [@id 0x0804] 334 + | RSA_PSS_RSAENC_SHA384 [@id 0x0805] 335 + | RSA_PSS_RSAENC_SHA512 [@id 0x0806] 336 + | ED25519 [@id 0x0807] 337 + | ED448 [@id 0x0808] 338 + | RSA_PSS_PSS_SHA256 [@id 0x0809] 339 + | RSA_PSS_PSS_SHA384 [@id 0x080a] 340 + | RSA_PSS_PSS_SHA512 [@id 0x080b] 341 + (* private use 0xFE00 - 0xFFFF *) 342 + 343 + let signature_alg_to_int = function 344 + | RSA_PKCS1_MD5 -> 0x0101 (* deprecated, TLS 1.2 only *) 345 + | RSA_PKCS1_SHA1 -> 0x0201 (* deprecated, TLS 1.2 only *) 346 + | RSA_PKCS1_SHA224 -> 0x0301 347 + | RSA_PKCS1_SHA256 -> 0x0401 348 + | RSA_PKCS1_SHA384 -> 0x0501 349 + | RSA_PKCS1_SHA512 -> 0x0601 350 + | ECDSA_SECP256R1_SHA1 -> 0x0203 (* deprecated, TLS 1.2 only *) 351 + | ECDSA_SECP256R1_SHA256 -> 0x0403 352 + | ECDSA_SECP384R1_SHA384 -> 0x0503 353 + | ECDSA_SECP521R1_SHA512 -> 0x0603 354 + | RSA_PSS_RSAENC_SHA256 -> 0x0804 355 + | RSA_PSS_RSAENC_SHA384 -> 0x0805 356 + | RSA_PSS_RSAENC_SHA512 -> 0x0806 357 + | ED25519 -> 0x0807 358 + | ED448 -> 0x0808 359 + | RSA_PSS_PSS_SHA256 -> 0x0809 360 + | RSA_PSS_PSS_SHA384 -> 0x080a 361 + | RSA_PSS_PSS_SHA512 -> 0x080b 362 + (* private use 0xFE00 - 0xFFFF *) 363 + and int_to_signature_alg = function 364 + | 0x0101 -> Some RSA_PKCS1_MD5 365 + | 0x0201 -> Some RSA_PKCS1_SHA1 366 + | 0x0301 -> Some RSA_PKCS1_SHA224 367 + | 0x0401 -> Some RSA_PKCS1_SHA256 368 + | 0x0501 -> Some RSA_PKCS1_SHA384 369 + | 0x0601 -> Some RSA_PKCS1_SHA512 370 + | 0x0203 -> Some ECDSA_SECP256R1_SHA1 371 + | 0x0403 -> Some ECDSA_SECP256R1_SHA256 372 + | 0x0503 -> Some ECDSA_SECP384R1_SHA384 373 + | 0x0603 -> Some ECDSA_SECP521R1_SHA512 374 + | 0x0804 -> Some RSA_PSS_RSAENC_SHA256 375 + | 0x0805 -> Some RSA_PSS_RSAENC_SHA384 376 + | 0x0806 -> Some RSA_PSS_RSAENC_SHA512 377 + | 0x0807 -> Some ED25519 378 + | 0x0808 -> Some ED448 379 + | 0x0809 -> Some RSA_PSS_PSS_SHA256 380 + | 0x080a -> Some RSA_PSS_PSS_SHA384 381 + | 0x080b -> Some RSA_PSS_PSS_SHA512 382 + | _ -> None 383 + 384 + let to_signature_alg = function 385 + | `RSA_PKCS1_MD5 -> RSA_PKCS1_MD5 386 + | `RSA_PKCS1_SHA1 -> RSA_PKCS1_SHA1 387 + | `RSA_PKCS1_SHA224 -> RSA_PKCS1_SHA224 388 + | `RSA_PKCS1_SHA256 -> RSA_PKCS1_SHA256 389 + | `RSA_PKCS1_SHA384 -> RSA_PKCS1_SHA384 390 + | `RSA_PKCS1_SHA512 -> RSA_PKCS1_SHA512 391 + | `RSA_PSS_RSAENC_SHA256 -> RSA_PSS_RSAENC_SHA256 392 + | `RSA_PSS_RSAENC_SHA384 -> RSA_PSS_RSAENC_SHA384 393 + | `RSA_PSS_RSAENC_SHA512 -> RSA_PSS_RSAENC_SHA512 394 + | `ECDSA_SECP256R1_SHA1 -> ECDSA_SECP256R1_SHA1 395 + | `ECDSA_SECP256R1_SHA256 -> ECDSA_SECP256R1_SHA256 396 + | `ECDSA_SECP384R1_SHA384 -> ECDSA_SECP384R1_SHA384 397 + | `ECDSA_SECP521R1_SHA512 -> ECDSA_SECP521R1_SHA512 398 + | `ED25519 -> ED25519 399 + 400 + let of_signature_alg = function 401 + | RSA_PKCS1_MD5 -> Some `RSA_PKCS1_MD5 402 + | RSA_PKCS1_SHA1 -> Some `RSA_PKCS1_SHA1 403 + | RSA_PKCS1_SHA224 -> Some `RSA_PKCS1_SHA224 404 + | RSA_PKCS1_SHA256 -> Some `RSA_PKCS1_SHA256 405 + | RSA_PKCS1_SHA384 -> Some `RSA_PKCS1_SHA384 406 + | RSA_PKCS1_SHA512 -> Some `RSA_PKCS1_SHA512 407 + | RSA_PSS_RSAENC_SHA256 -> Some `RSA_PSS_RSAENC_SHA256 408 + | RSA_PSS_RSAENC_SHA384 -> Some `RSA_PSS_RSAENC_SHA384 409 + | RSA_PSS_RSAENC_SHA512 -> Some `RSA_PSS_RSAENC_SHA512 410 + | ECDSA_SECP256R1_SHA1 -> Some `ECDSA_SECP256R1_SHA1 411 + | ECDSA_SECP256R1_SHA256 -> Some `ECDSA_SECP256R1_SHA256 412 + | ECDSA_SECP384R1_SHA384 -> Some `ECDSA_SECP384R1_SHA384 413 + | ECDSA_SECP521R1_SHA512 -> Some `ECDSA_SECP521R1_SHA512 414 + | ED25519 -> Some `ED25519 415 + | _ -> None 416 + 417 + (* EC RFC4492*) 418 + type ec_curve_type = 419 + (* 1 and 2 are deprecated in RFC 8422 *) 420 + | NAMED_CURVE [@id 3] 421 + 422 + let ec_curve_type_to_int = function 423 + | NAMED_CURVE -> 3 424 + and int_to_ec_curve_type = function 425 + | 3 -> Some NAMED_CURVE 426 + | _ -> None 427 + 428 + type named_group = 429 + (* OBSOLETE_RESERVED 0x0001 - 0x0016 *) 430 + | SECP256R1 [@id 23] 431 + | SECP384R1 [@id 24] 432 + | SECP521R1 [@id 25] 433 + (* OBSOLETE_RESERVED 0x001A - 0x001C *) 434 + | X25519 [@id 29] (*RFC8446*) 435 + | X448 [@id 30] (*RFC8446*) 436 + | FFDHE2048 [@id 256] (*RFC8446*) 437 + | FFDHE3072 [@id 257] (*RFC8446*) 438 + | FFDHE4096 [@id 258] (*RFC8446*) 439 + | FFDHE6144 [@id 259] (*RFC8446*) 440 + | FFDHE8192 [@id 260] (*RFC8446*) 441 + (* FFDHE_PRIVATE_USE 0x01FC - 0x01FF *) 442 + (* ECDHE_PRIVATE_USE 0xFE00 - 0xFEFF *) 443 + (* OBSOLETE_RESERVED 0xFF01 - 0xFF02 *) 444 + 445 + let named_group_to_int = function 446 + | SECP256R1 -> 23 447 + | SECP384R1 -> 24 448 + | SECP521R1 -> 25 449 + (* OBSOLETE_RESERVED 0x001A - 0x001C *) 450 + | X25519 -> 29 (*RFC8446*) 451 + | X448 -> 30 (*RFC8446*) 452 + | FFDHE2048 -> 256 (*RFC8446*) 453 + | FFDHE3072 -> 257 (*RFC8446*) 454 + | FFDHE4096 -> 258 (*RFC8446*) 455 + | FFDHE6144 -> 259 (*RFC8446*) 456 + | FFDHE8192 -> 260 (*RFC8446*) 457 + (* FFDHE_PRIVATE_USE 0x01FC - 0x01FF *) 458 + (* ECDHE_PRIVATE_USE 0xFE00 - 0xFEFF *) 459 + (* OBSOLETE_RESERVED 0xFF01 - 0xFF02 *) 460 + and int_to_named_group = function 461 + | 23 -> Some SECP256R1 462 + | 24 -> Some SECP384R1 463 + | 25 -> Some SECP521R1 464 + | 29 -> Some X25519 465 + | 30 -> Some X448 466 + | 256 -> Some FFDHE2048 467 + | 257 -> Some FFDHE3072 468 + | 258 -> Some FFDHE4096 469 + | 259 -> Some FFDHE6144 470 + | 260 -> Some FFDHE8192 471 + | _ -> None 472 + 473 + (** enum of all TLS ciphersuites *) 474 + type any_ciphersuite = 475 + | TLS_RSA_WITH_3DES_EDE_CBC_SHA [@id 0x000A] 476 + | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA [@id 0x0016] 477 + (* from RFC 3268 *) 478 + | TLS_RSA_WITH_AES_128_CBC_SHA [@id 0x002F] 479 + | TLS_DHE_RSA_WITH_AES_128_CBC_SHA [@id 0x0033] 480 + | TLS_RSA_WITH_AES_256_CBC_SHA [@id 0x0035] 481 + | TLS_DHE_RSA_WITH_AES_256_CBC_SHA [@id 0x0039] 482 + (* from RFC 5246 *) 483 + | TLS_RSA_WITH_AES_128_CBC_SHA256 [@id 0x003C] 484 + | TLS_RSA_WITH_AES_256_CBC_SHA256 [@id 0x003D] 485 + | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 [@id 0x0067] 486 + | TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 [@id 0x006B] 487 + | TLS_RSA_WITH_AES_128_GCM_SHA256 [@id 0x009C] (*RFC5288*) 488 + | TLS_RSA_WITH_AES_256_GCM_SHA384 [@id 0x009D] (*RFC5288*) 489 + | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 [@id 0x009E] (*RFC5288*) 490 + | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 [@id 0x009F] (*RFC5288*) 491 + | TLS_EMPTY_RENEGOTIATION_INFO_SCSV [@id 0x00FF] (*RFC5746*) 492 + | TLS_AES_128_GCM_SHA256 [@id 0x1301] (*RFC8446*) 493 + | TLS_AES_256_GCM_SHA384 [@id 0x1302] (*RFC8446*) 494 + | TLS_CHACHA20_POLY1305_SHA256 [@id 0x1303] (*RFC8446*) 495 + | TLS_AES_128_CCM_SHA256 [@id 0x1304] (*RFC8446*) 496 + | TLS_FALLBACK_SCSV [@id 0x5600] (*draft-ietf-tls-downgrade-scsv*) 497 + (* from RFC 4492 *) 498 + | TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA [@id 0xC008] 499 + | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA [@id 0xC009] 500 + | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA [@id 0xC00A] 501 + | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA [@id 0xC012] 502 + | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA [@id 0xC013] 503 + | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA [@id 0xC014] 504 + | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 [@id 0xC023] (*RFC5289*) 505 + | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 [@id 0xC024] (*RFC5289*) 506 + | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 [@id 0xC027] (*RFC5289*) 507 + | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 [@id 0xC028] (*RFC5289*) 508 + | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 [@id 0xC02B] (*RFC5289*) 509 + | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 [@id 0xC02C] (*RFC5289*) 510 + | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [@id 0xC02F] (*RFC5289*) 511 + | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 [@id 0xC030] (*RFC5289*) 512 + | TLS_RSA_WITH_AES_128_CCM [@id 0xC09C] (*RFC6655*) 513 + | TLS_RSA_WITH_AES_256_CCM [@id 0xC09D] (*RFC6655*) 514 + | TLS_DHE_RSA_WITH_AES_128_CCM [@id 0xC09E] (*RFC6655*) 515 + | TLS_DHE_RSA_WITH_AES_256_CCM [@id 0xC09F] (*RFC6655*) 516 + | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 [@id 0xCCA8] (*RFC7905*) 517 + | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 [@id 0xCCA9] (*RFC7905*) 518 + | TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 [@id 0xCCAA] (*RFC7905*) 519 + 520 + let any_ciphersuite_to_int = function 521 + | TLS_RSA_WITH_3DES_EDE_CBC_SHA -> 0x000A 522 + | TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA -> 0x0016 523 + | TLS_RSA_WITH_AES_128_CBC_SHA -> 0x002F 524 + | TLS_DHE_RSA_WITH_AES_128_CBC_SHA -> 0x0033 525 + | TLS_RSA_WITH_AES_256_CBC_SHA -> 0x0035 526 + | TLS_DHE_RSA_WITH_AES_256_CBC_SHA -> 0x0039 527 + | TLS_RSA_WITH_AES_128_CBC_SHA256 -> 0x003C 528 + | TLS_RSA_WITH_AES_256_CBC_SHA256 -> 0x003D 529 + | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 -> 0x0067 530 + | TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 -> 0x006B 531 + | TLS_RSA_WITH_AES_128_GCM_SHA256 -> 0x009C (*RFC5288*) 532 + | TLS_RSA_WITH_AES_256_GCM_SHA384 -> 0x009D (*RFC5288*) 533 + | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 -> 0x009E (*RFC5288*) 534 + | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 -> 0x009F (*RFC5288*) 535 + | TLS_EMPTY_RENEGOTIATION_INFO_SCSV -> 0x00FF (*RFC5746*) 536 + | TLS_AES_128_GCM_SHA256 -> 0x1301 (*RFC8446*) 537 + | TLS_AES_256_GCM_SHA384 -> 0x1302 (*RFC8446*) 538 + | TLS_CHACHA20_POLY1305_SHA256 -> 0x1303 (*RFC8446*) 539 + | TLS_AES_128_CCM_SHA256 -> 0x1304 (*RFC8446*) 540 + | TLS_FALLBACK_SCSV -> 0x5600 (*draft-ietf-tls-downgrade-scsv*) 541 + | TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA -> 0xC008 542 + | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA -> 0xC009 543 + | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA -> 0xC00A 544 + | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA -> 0xC012 545 + | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA -> 0xC013 546 + | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA -> 0xC014 547 + | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 -> 0xC023 (*RFC5289*) 548 + | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 -> 0xC024 (*RFC5289*) 549 + | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 -> 0xC027 (*RFC5289*) 550 + | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 -> 0xC028 (*RFC5289*) 551 + | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -> 0xC02B (*RFC5289*) 552 + | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -> 0xC02C (*RFC5289*) 553 + | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -> 0xC02F (*RFC5289*) 554 + | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -> 0xC030 (*RFC5289*) 555 + | TLS_RSA_WITH_AES_128_CCM -> 0xC09C (*RFC6655*) 556 + | TLS_RSA_WITH_AES_256_CCM -> 0xC09D (*RFC6655*) 557 + | TLS_DHE_RSA_WITH_AES_128_CCM -> 0xC09E (*RFC6655*) 558 + | TLS_DHE_RSA_WITH_AES_256_CCM -> 0xC09F (*RFC6655*) 559 + | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> 0xCCA8 (*RFC7905*) 560 + | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -> 0xCCA9 (*RFC7905*) 561 + | TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -> 0xCCAA (*RFC7905*) 562 + 563 + and int_to_any_ciphersuite = function 564 + | 0x000A -> Some TLS_RSA_WITH_3DES_EDE_CBC_SHA 565 + | 0x0016 -> Some TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 566 + | 0x002F -> Some TLS_RSA_WITH_AES_128_CBC_SHA 567 + | 0x0033 -> Some TLS_DHE_RSA_WITH_AES_128_CBC_SHA 568 + | 0x0035 -> Some TLS_RSA_WITH_AES_256_CBC_SHA 569 + | 0x0039 -> Some TLS_DHE_RSA_WITH_AES_256_CBC_SHA 570 + | 0x003C -> Some TLS_RSA_WITH_AES_128_CBC_SHA256 571 + | 0x003D -> Some TLS_RSA_WITH_AES_256_CBC_SHA256 572 + | 0x0067 -> Some TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 573 + | 0x006B -> Some TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 574 + | 0x009C -> Some TLS_RSA_WITH_AES_128_GCM_SHA256 575 + | 0x009D -> Some TLS_RSA_WITH_AES_256_GCM_SHA384 576 + | 0x009E -> Some TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 577 + | 0x009F -> Some TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 578 + | 0x00FF -> Some TLS_EMPTY_RENEGOTIATION_INFO_SCSV 579 + | 0x1301 -> Some TLS_AES_128_GCM_SHA256 580 + | 0x1302 -> Some TLS_AES_256_GCM_SHA384 581 + | 0x1303 -> Some TLS_CHACHA20_POLY1305_SHA256 582 + | 0x1304 -> Some TLS_AES_128_CCM_SHA256 583 + | 0x5600 -> Some TLS_FALLBACK_SCSV 584 + | 0xC008 -> Some TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 585 + | 0xC009 -> Some TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 586 + | 0xC00A -> Some TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 587 + | 0xC012 -> Some TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 588 + | 0xC013 -> Some TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 589 + | 0xC014 -> Some TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 590 + | 0xC023 -> Some TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 591 + | 0xC024 -> Some TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 592 + | 0xC027 -> Some TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 593 + | 0xC028 -> Some TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 594 + | 0xC02B -> Some TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 595 + | 0xC02C -> Some TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 596 + | 0xC02F -> Some TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 597 + | 0xC030 -> Some TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 598 + | 0xC09C -> Some TLS_RSA_WITH_AES_128_CCM 599 + | 0xC09D -> Some TLS_RSA_WITH_AES_256_CCM 600 + | 0xC09E -> Some TLS_DHE_RSA_WITH_AES_128_CCM 601 + | 0xC09F -> Some TLS_DHE_RSA_WITH_AES_256_CCM 602 + | 0xCCA8 -> Some TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 603 + | 0xCCA9 -> Some TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 604 + | 0xCCAA -> Some TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 605 + | _ -> None 606 + 607 + type key_update_request_type = 608 + | UPDATE_NOT_REQUESTED [@id 0] 609 + | UPDATE_REQUESTED [@id 1] 610 + 611 + let key_update_request_type_to_int = function 612 + | UPDATE_NOT_REQUESTED -> 0 613 + | UPDATE_REQUESTED -> 1 614 + and int_to_key_update_request_type = function 615 + | 0 -> Some UPDATE_NOT_REQUESTED 616 + | 1 -> Some UPDATE_REQUESTED 617 + | _ -> None 618 + 619 + let helloretryrequest = Digestif.SHA256.(to_raw_string (digest_string "HelloRetryRequest")) 620 + let downgrade12 = "\x44\x4F\x57\x4E\x47\x52\x44\x01" 621 + let downgrade11 = "\x44\x4F\x57\x4E\x47\x52\x44\x00"
+815
vendor/opam/tls/lib/reader.ml
··· 1 + open Packet 2 + open Core 3 + 4 + type error = 5 + | TrailingBytes of string 6 + | WrongLength of string 7 + | Unknown of string 8 + 9 + exception Reader_error of error 10 + 11 + let raise_unknown msg = raise (Reader_error (Unknown msg)) 12 + and raise_wrong_length msg = raise (Reader_error (WrongLength msg)) 13 + and raise_trailing_bytes msg = raise (Reader_error (TrailingBytes msg)) 14 + 15 + let shift str amount = String.sub str amount (String.length str - amount) 16 + 17 + let catch f x = 18 + try Ok (f x) with 19 + | Reader_error TrailingBytes msg -> Error (`Decode ("trailing bytes: " ^ msg)) 20 + | Reader_error WrongLength msg -> Error (`Decode ("wrong length: " ^ msg)) 21 + | Reader_error Unknown msg -> Error (`Decode msg) 22 + | Invalid_argument msg -> Error (`Decode msg) 23 + 24 + let parse_version_int buf = 25 + let major = String.get_uint8 buf 0 in 26 + let minor = String.get_uint8 buf 1 in 27 + (major, minor) 28 + 29 + let parse_version_exn buf = 30 + let version = parse_version_int buf in 31 + match tls_version_of_pair version with 32 + | Some x -> x 33 + | None -> raise_unknown "version" 34 + 35 + let parse_any_version_opt buf = 36 + let version = parse_version_int buf in 37 + tls_any_version_of_pair version, shift buf 2 38 + 39 + let parse_any_version_exn buf = 40 + match parse_any_version_opt buf with 41 + | Some x, _ -> x 42 + | None, _ -> raise_unknown "version" 43 + 44 + let parse_version = catch parse_version_exn 45 + 46 + let parse_any_version = catch parse_any_version_exn 47 + 48 + let parse_record buf = 49 + if String.length buf < 5 then 50 + Ok (`Fragment buf) 51 + else 52 + let typ = String.get_uint8 buf 0 53 + and version = parse_version_int (shift buf 1) 54 + in 55 + match String.get_uint16_be buf 3 with 56 + | x when x > (1 lsl 14 + 2048) -> 57 + (* 2 ^ 14 + 2048 for TLSCiphertext 58 + 2 ^ 14 + 1024 for TLSCompressed 59 + 2 ^ 14 for TLSPlaintext *) 60 + Error (`Record_overflow x) 61 + | x when 5 + x > String.length buf -> Ok (`Fragment buf) 62 + | x -> 63 + match 64 + tls_any_version_of_pair version, 65 + int_to_content_type typ 66 + with 67 + | None, _ -> Error (`Protocol_version (`Unknown_record version)) 68 + | _, None -> Error (`Unexpected (`Content_type typ)) 69 + | Some version, Some content_type -> 70 + let payload, rest = split_str ~start:5 buf x in 71 + Ok (`Record (({ content_type ; version }, payload), rest)) 72 + 73 + let validate_alert (lvl, typ) = 74 + let open Packet in 75 + match lvl, typ with 76 + (* from RFC, find out which ones must be always FATAL 77 + and report if this does not meet the expectations *) 78 + | WARNING, (UNEXPECTED_MESSAGE | BAD_RECORD_MAC | RECORD_OVERFLOW 79 + | HANDSHAKE_FAILURE | BAD_CERTIFICATE | DECODE_ERROR 80 + | PROTOCOL_VERSION | INAPPROPRIATE_FALLBACK | MISSING_EXTENSION 81 + | UNSUPPORTED_EXTENSION | UNRECOGNIZED_NAME | 82 + NO_APPLICATION_PROTOCOL as x) -> 83 + raise_unknown (alert_type_to_string x ^ " must always be fatal") 84 + 85 + (* those are always warnings *) 86 + | FATAL, (USER_CANCELED | NO_RENEGOTIATION as x) -> 87 + raise_unknown (alert_type_to_string x ^ " must always be a warning") 88 + 89 + | lvl, typ -> (lvl, typ) 90 + 91 + let parse_alert = catch @@ fun buf -> 92 + if String.length buf <> 2 then 93 + raise_trailing_bytes "after alert" 94 + else 95 + let level = String.get_uint8 buf 0 in 96 + let typ = String.get_uint8 buf 1 in 97 + match int_to_alert_level level, int_to_alert_type typ with 98 + | (Some lvl, msg) -> validate_alert (lvl, msg) 99 + | _ -> raise_unknown @@ "alert level " ^ string_of_int level 100 + 101 + let parse_change_cipher_spec buf = 102 + match String.length buf, String.get_uint8 buf 0 with 103 + | 1, 1 -> Ok () 104 + | _ -> Error (`Decode "bad change cipher spec message") 105 + 106 + let rec parse_count_list parsef buf acc = function 107 + | 0 -> (List.rev acc, buf) 108 + | n -> 109 + match parsef buf with 110 + | Some elem, buf' -> parse_count_list parsef buf' (elem :: acc) (pred n) 111 + | None , buf' -> parse_count_list parsef buf' acc (pred n) 112 + 113 + let rec parse_list parsef buf acc = 114 + match String.length buf with 115 + | 0 -> List.rev acc 116 + | _ -> 117 + match parsef buf with 118 + | Some elem, buf' -> parse_list parsef buf' (elem :: acc) 119 + | None , buf' -> parse_list parsef buf' acc 120 + 121 + let parse_compression_method buf = 122 + let cm = String.get_uint8 buf 0 in 123 + (int_to_compression_method cm, shift buf 1) 124 + 125 + let parse_compression_methods buf = 126 + let count = String.get_uint8 buf 0 in 127 + parse_count_list parse_compression_method (shift buf 1) [] count 128 + 129 + let parse_any_ciphersuite buf = 130 + let typ = String.get_uint16_be buf 0 in 131 + (int_to_any_ciphersuite typ, shift buf 2) 132 + 133 + let parse_any_ciphersuites buf = 134 + let count = String.get_uint16_be buf 0 in 135 + if count mod 2 <> 0 then 136 + raise_wrong_length "ciphersuite list" 137 + else 138 + parse_count_list parse_any_ciphersuite (shift buf 2) [] (count / 2) 139 + 140 + let parse_ciphersuite buf = 141 + match parse_any_ciphersuite buf with 142 + | None , buf' -> (None, buf') 143 + | Some cs, buf' -> match Ciphersuite.any_ciphersuite_to_ciphersuite cs with 144 + | None -> (None, buf') 145 + | Some cs' -> (Some cs', buf') 146 + 147 + let parse_hostnames buf = 148 + match String.length buf with 149 + | 0 -> [] 150 + | n -> 151 + let parsef buf = 152 + let typ = String.get_uint8 buf 0 in 153 + let entrylen = String.get_uint16_be buf 1 in 154 + let rt = shift buf (3 + entrylen) in 155 + match typ with 156 + | 0 -> let hostname = String.sub buf 3 entrylen in 157 + (Some hostname, rt) 158 + | _ -> (None, rt) 159 + in 160 + let list_length = String.get_uint16_be buf 0 in 161 + if list_length + 2 <> n then 162 + raise_trailing_bytes "hostname" 163 + else 164 + parse_list parsef (String.sub buf 2 list_length) [] 165 + 166 + let parse_fragment_length buf = 167 + if String.length buf <> 1 then 168 + raise_trailing_bytes "fragment length" 169 + else 170 + int_to_max_fragment_length (String.get_uint8 buf 0) 171 + 172 + let parse_supported_version buf = 173 + parse_any_version_opt buf 174 + 175 + let parse_supported_versions buf = 176 + let len = String.get_uint8 buf 0 in 177 + if len mod 2 <> 0 then 178 + raise_wrong_length "supported versions" 179 + else 180 + parse_count_list parse_supported_version (shift buf 1) [] (len / 2) 181 + 182 + let parse_named_group buf = 183 + let typ = String.get_uint16_be buf 0 in 184 + (int_to_named_group typ, shift buf 2) 185 + 186 + let parse_group buf = 187 + match parse_named_group buf with 188 + | Some x, buf -> (named_group_to_group x, buf) 189 + | None, buf -> (None, buf) 190 + 191 + let parse_supported_groups buf = 192 + let count = String.get_uint16_be buf 0 in 193 + if count mod 2 <> 0 then 194 + raise_wrong_length "elliptic curve list" 195 + else 196 + let cs, rt = parse_count_list parse_named_group (shift buf 2) [] (count / 2) in 197 + if String.length rt <> 0 then 198 + raise_trailing_bytes "elliptic curves" 199 + else 200 + cs 201 + 202 + let parse_signature_algorithm buf = 203 + match int_to_signature_alg (String.get_uint16_be buf 0) with 204 + | Some sig_alg -> of_signature_alg sig_alg 205 + | _ -> None 206 + 207 + let parse_signature_algorithms buf = 208 + let parsef buf = parse_signature_algorithm buf, shift buf 2 in 209 + let count = String.get_uint16_be buf 0 in 210 + if count mod 2 <> 0 then 211 + raise_wrong_length "signature hash" 212 + else 213 + parse_count_list parsef (shift buf 2) [] (count / 2) 214 + 215 + let parse_alpn_protocol raw = 216 + let length = String.get_uint8 raw 0 in 217 + let protocol = String.sub raw 1 length in 218 + (Some protocol, shift raw (1 + length)) 219 + 220 + let parse_alpn_protocols buf = 221 + let len = String.get_uint16_be buf 0 in 222 + if String.length buf <> len + 2 then 223 + raise_trailing_bytes "alpn" 224 + else 225 + parse_list parse_alpn_protocol (String.sub buf 2 len) [] 226 + 227 + let parse_ec_point_format buf = 228 + (* this is deprecated, we only check that uncompressed (typ 0) is present *) 229 + let data = String.get_uint8 buf 0 in 230 + Some (data = 0), shift buf 1 231 + 232 + let parse_ec_point_formats buf = 233 + let count = String.get_uint8 buf 0 in 234 + parse_count_list parse_ec_point_format (shift buf 1) [] count 235 + 236 + let parse_extension buf = function 237 + | MAX_FRAGMENT_LENGTH -> 238 + (match parse_fragment_length buf with 239 + | Some mfl -> `MaxFragmentLength mfl 240 + | None -> raise_unknown "maximum fragment length") 241 + | RENEGOTIATION_INFO -> 242 + let len' = String.get_uint8 buf 0 in 243 + if String.length buf <> len' + 1 then 244 + raise_trailing_bytes "renegotiation" 245 + else 246 + `SecureRenegotiation (String.sub buf 1 len') 247 + | EXTENDED_MASTER_SECRET -> 248 + if String.length buf > 0 then 249 + raise_trailing_bytes "extended master secret" 250 + else 251 + `ExtendedMasterSecret 252 + | EC_POINT_FORMATS -> 253 + let formats, rt = parse_ec_point_formats buf in 254 + if String.length rt <> 0 then 255 + raise_trailing_bytes "ec point formats" 256 + else if List.mem true formats then 257 + `ECPointFormats 258 + else 259 + raise_unknown "EC Point Formats without uncompressed" 260 + | x -> `UnknownExtension (extension_type_to_int x, buf) 261 + 262 + let parse_keyshare_entry buf = 263 + let parse_share data = 264 + let size = String.get_uint16_be data 0 in 265 + split_str ~start:2 data size 266 + in 267 + let g, rest = parse_named_group buf in 268 + let share, left = parse_share rest in 269 + match g with 270 + | None -> None, left 271 + | Some g -> Some (g, share), left 272 + 273 + let parse_id buf = 274 + let id_len = String.get_uint16_be buf 0 in 275 + if id_len = 0 then (* id must be non-empty! *) 276 + raise_wrong_length "PSK id is empty" 277 + else 278 + let age = String.get_int32_be buf (id_len + 2) in 279 + (Some (String.sub buf 2 id_len, age), shift buf (id_len + 6)) 280 + 281 + let parse_binder buf = 282 + let l = String.get_uint8 buf 0 in 283 + Some (String.sub buf 1 l), shift buf (l + 1) 284 + 285 + let parse_client_presharedkeys buf = 286 + let id_len = String.get_uint16_be buf 0 in 287 + let identities = parse_list parse_id (String.sub buf 2 id_len) [] in 288 + let binders_len = String.get_uint16_be buf (id_len + 2) in 289 + let binders = parse_list parse_binder (String.sub buf (4 + id_len) binders_len) [] in 290 + let id_binder = List.combine identities binders in 291 + if String.length buf <> 4 + binders_len + id_len then 292 + raise_trailing_bytes "psk" 293 + else 294 + id_binder 295 + 296 + let parse_cookie buf = 297 + let len = String.get_uint16_be buf 0 in 298 + (String.sub buf 2 len, shift buf (2 + len)) 299 + 300 + let parse_psk_key_exchange_mode buf = 301 + let data = String.get_uint8 buf 0 in 302 + (int_to_psk_key_exchange_mode data, shift buf 1) 303 + 304 + let parse_psk_key_exchange_modes buf = 305 + let count = String.get_uint8 buf 0 in 306 + parse_count_list parse_psk_key_exchange_mode (shift buf 1) [] count 307 + 308 + let parse_ext raw = 309 + let etype = String.get_uint16_be raw 0 310 + and length = String.get_uint16_be raw 2 311 + in 312 + (etype, length, String.sub raw 4 length) 313 + 314 + let parse_client_extension raw = 315 + let etype, len, buf = parse_ext raw in 316 + let data = 317 + match int_to_extension_type etype with 318 + | Some SERVER_NAME -> 319 + (match parse_hostnames buf with 320 + | [name] -> 321 + (match Domain_name.of_string name with 322 + | Error (`Msg err) -> 323 + raise_unknown ("unable to canonicalize " ^ name ^ "into a domain name: " ^ err) 324 + | Ok domain_name -> 325 + (match Domain_name.host domain_name with 326 + | Error (`Msg err) -> 327 + raise_unknown ("unable to build a hostname from " ^ name ^ ": " ^ err) 328 + | Ok hostname -> `Hostname hostname)) 329 + | _ -> raise_unknown "bad server name indication (multiple names)") 330 + | Some SUPPORTED_GROUPS -> 331 + let gs = parse_supported_groups buf in 332 + `SupportedGroups gs 333 + | Some PADDING -> 334 + let rec check = function 335 + | 0 -> `Padding len 336 + | n -> let idx = pred n in 337 + if String.get_uint8 buf idx <> 0 then 338 + raise_unknown "bad padding in padding extension" 339 + else 340 + check idx 341 + in 342 + check len 343 + | Some SIGNATURE_ALGORITHMS -> 344 + let algos, rt = parse_signature_algorithms buf in 345 + if String.length rt <> 0 then 346 + raise_trailing_bytes "signature algorithms" 347 + else 348 + `SignatureAlgorithms algos 349 + | Some APPLICATION_LAYER_PROTOCOL_NEGOTIATION -> 350 + let protocols = parse_alpn_protocols buf in 351 + `ALPN protocols 352 + | Some KEY_SHARE -> 353 + let ll = String.get_uint16_be buf 0 in 354 + if ll + 2 <> String.length buf then 355 + raise_unknown "bad key share extension" 356 + else 357 + let shares = parse_list parse_keyshare_entry (String.sub buf 2 ll) [] in 358 + `KeyShare shares 359 + | Some PRE_SHARED_KEY -> 360 + let ids = parse_client_presharedkeys buf in 361 + `PreSharedKeys ids 362 + | Some EARLY_DATA -> 363 + if String.length buf <> 0 then 364 + raise_trailing_bytes "early data" 365 + else 366 + `EarlyDataIndication 367 + | Some SUPPORTED_VERSIONS -> 368 + let versions, rt = parse_supported_versions buf in 369 + if String.length rt <> 0 then 370 + raise_trailing_bytes "supported versions" 371 + else 372 + `SupportedVersions versions 373 + | Some POST_HANDSHAKE_AUTH -> 374 + if String.length buf = 0 then 375 + `PostHandshakeAuthentication 376 + else 377 + raise_unknown "non-empty post handshake authentication" 378 + | Some COOKIE -> 379 + let c, rt = parse_cookie buf in 380 + if String.length rt <> 0 then 381 + raise_trailing_bytes "cookie" 382 + else 383 + `Cookie c 384 + | Some PSK_KEY_EXCHANGE_MODES -> 385 + let modes, rt = parse_psk_key_exchange_modes buf in 386 + if String.length rt <> 0 then 387 + raise_trailing_bytes "psk key exchange modes" 388 + else 389 + `PskKeyExchangeModes modes 390 + | Some x -> parse_extension buf x 391 + | None -> `UnknownExtension (etype, buf) 392 + in 393 + (Some data, shift raw (4 + len)) 394 + 395 + let parse_server_extension raw = 396 + let etype, len, buf = parse_ext raw in 397 + let data = 398 + match int_to_extension_type etype with 399 + | Some SERVER_NAME -> 400 + (match parse_hostnames buf with 401 + | [] -> `Hostname 402 + | _ -> raise_unknown "bad server name indication (multiple names)") 403 + | Some KEY_SHARE -> 404 + (match parse_keyshare_entry buf with 405 + | _, xs when String.length xs <> 0 -> raise_trailing_bytes "server keyshare" 406 + | None, _ -> raise_unknown "keyshare entry" 407 + | Some (g, ks), _ -> 408 + match named_group_to_group g with 409 + | Some g -> `KeyShare (g, ks) 410 + | None -> raise_unknown "keyshare entry") 411 + | Some PRE_SHARED_KEY -> 412 + if String.length buf <> 2 then 413 + raise_trailing_bytes "server pre_shared_key" 414 + else 415 + `PreSharedKey (String.get_uint16_be buf 0) 416 + | Some SUPPORTED_GROUPS | Some SIGNATURE_ALGORITHMS | Some PADDING -> 417 + raise_unknown "invalid extension in server hello!" 418 + | Some APPLICATION_LAYER_PROTOCOL_NEGOTIATION -> 419 + (match parse_alpn_protocols buf with 420 + | [protocol] -> `ALPN protocol 421 + | _ -> raise_unknown "bad ALPN (none or multiple names)") 422 + | Some SUPPORTED_VERSIONS -> 423 + let version = parse_version_exn buf in 424 + `SelectedVersion version 425 + | Some x -> parse_extension buf x 426 + | None -> `UnknownExtension (etype, buf) 427 + in 428 + (Some data, shift raw (4 + len)) 429 + 430 + let parse_encrypted_extension raw = 431 + let etype, len, buf = parse_ext raw in 432 + let data = 433 + match int_to_extension_type etype with 434 + | Some SERVER_NAME -> 435 + (match parse_hostnames buf with 436 + | [] -> `Hostname 437 + | _ -> raise_unknown "bad server name indication (multiple names)") 438 + | Some SUPPORTED_GROUPS -> 439 + let gs = parse_supported_groups buf in 440 + let supported = List.filter_map named_group_to_group gs in 441 + `SupportedGroups supported 442 + | Some APPLICATION_LAYER_PROTOCOL_NEGOTIATION -> 443 + (match parse_alpn_protocols buf with 444 + | [protocol] -> `ALPN protocol 445 + | _ -> raise_unknown "bad ALPN (none or multiple names)") 446 + | Some EARLY_DATA -> 447 + if String.length buf <> 0 then 448 + raise_trailing_bytes "server early_data" 449 + else 450 + `EarlyDataIndication 451 + | Some x -> raise_unknown ("bad encrypted extension " ^ (extension_type_to_string x)) (* TODO maybe unknown instead? *) 452 + | None -> `UnknownExtension (etype, buf) 453 + in 454 + (Some data, shift raw (4 + len)) 455 + 456 + let parse_retry_extension raw = 457 + let etype, len, buf = parse_ext raw in 458 + let data = 459 + match int_to_extension_type etype with 460 + | Some KEY_SHARE -> 461 + begin 462 + let group, rt = parse_group buf in 463 + if String.length rt <> 0 then 464 + raise_trailing_bytes "key share" 465 + else 466 + match group with 467 + | None -> raise_unknown "unknown group in key share" 468 + | Some g -> `SelectedGroup g 469 + end 470 + | Some SUPPORTED_VERSIONS -> 471 + let version = parse_version_exn buf in 472 + `SelectedVersion version 473 + | Some COOKIE -> 474 + let c, rt = parse_cookie buf in 475 + if String.length rt <> 0 then 476 + raise_trailing_bytes "cookie" 477 + else 478 + `Cookie c 479 + | _ -> `UnknownExtension (etype, buf) 480 + in 481 + (Some data, shift raw (4 + len)) 482 + 483 + let parse_extensions parse_ext buf = 484 + let len = String.get_uint16_be buf 0 in 485 + if String.length buf <> len + 2 then 486 + raise_trailing_bytes "extensions" 487 + else 488 + parse_list parse_ext (String.sub buf 2 len) [] 489 + 490 + let parse_client_hello buf = 491 + let client_version = parse_any_version_exn buf in 492 + let client_random = String.sub buf 2 32 in 493 + let slen = String.get_uint8 buf 34 in 494 + let sessionid = if slen = 0 then None else Some (String.sub buf 35 slen) in 495 + let ciphersuites, rt = parse_any_ciphersuites (shift buf (35 + slen)) in 496 + let _, rt' = parse_compression_methods rt in 497 + let extensions = 498 + if String.length rt' = 0 then [] else parse_extensions parse_client_extension rt' 499 + in 500 + (* TLS 1.3 mandates PreSharedKeys to be the last extension *) 501 + (if List.exists (function `PreSharedKeys _ -> true | _ -> false) extensions then 502 + match List.rev extensions with 503 + | `PreSharedKeys _::_ -> () 504 + | _ -> raise_unknown "Pre-shared key extension exists, but is not the last"); 505 + ClientHello { client_version ; client_random ; sessionid ; ciphersuites ; extensions } 506 + 507 + let parse_server_hello buf = 508 + let server_version = parse_version_exn buf in 509 + let server_random = String.sub buf 2 32 in 510 + let slen = String.get_uint8 buf 34 in 511 + let sessionid = if slen = 0 then None else Some (String.sub buf 35 slen) in 512 + let ciphersuite, rt = match parse_ciphersuite (shift buf (35 + slen)) with 513 + | Some x, buf' -> (x, buf') 514 + | None , _ -> raise_unknown "ciphersuite" 515 + in 516 + let rt' = match parse_compression_method rt with 517 + | Some NULL, buf' -> buf' 518 + | None , _ -> raise_unknown "compression method" 519 + in 520 + (* depending on the content of the server_random we have to diverge in behaviour *) 521 + if String.equal server_random helloretryrequest then begin 522 + (* hello retry request, TODO: verify compression=empty *) 523 + match Ciphersuite.ciphersuite_to_ciphersuite13 ciphersuite with 524 + | None -> raise_unknown "unsupported ciphersuite in hello retry request" 525 + | Some ciphersuite -> 526 + let extensions = 527 + if String.length rt' = 0 then [] else parse_extensions parse_retry_extension rt' 528 + in 529 + let retry_version = 530 + match Utils.map_find ~f:(function `SelectedVersion v -> Some v | _ -> None) extensions with 531 + | None -> server_version 532 + | Some v -> v 533 + in 534 + let selected_group = 535 + match Utils.map_find ~f:(function `SelectedGroup g -> Some g | _ -> None) extensions with 536 + | None -> raise_unknown "unknown selected group" 537 + | Some g -> g 538 + in 539 + HelloRetryRequest { retry_version ; sessionid ; ciphersuite ; selected_group ; extensions } 540 + end else begin 541 + let extensions = 542 + if String.length rt' = 0 then [] else parse_extensions parse_server_extension rt' 543 + in 544 + let server_version = 545 + match Utils.map_find ~f:(function `SelectedVersion v -> Some v | _ -> None) extensions with 546 + | None -> server_version 547 + | Some v -> v 548 + in 549 + ServerHello { server_version ; server_random ; sessionid ; ciphersuite ; extensions } 550 + end 551 + 552 + let parse_certificates_exn buf = 553 + let parsef buf = 554 + let len = get_uint24_len ~off:0 buf in 555 + (Some (String.sub buf 3 len), shift buf (len + 3)) 556 + in 557 + let len = get_uint24_len ~off:0 buf in 558 + if String.length buf <> len + 3 then 559 + raise_trailing_bytes "certificates" 560 + else 561 + parse_list parsef (String.sub buf 3 len) [] 562 + 563 + let parse_certificates = catch @@ parse_certificates_exn 564 + 565 + (* TODO finish implementation of certificate extensions *) 566 + let parse_certificate_ext _ = None, "" 567 + 568 + let parse_certificate_ext_1_3_exn buf = 569 + let certlen = get_uint24_len ~off:0 buf in 570 + let cert, extbuf, rest = 571 + let cert, rt = split_str ~start:3 buf certlen in 572 + let ext_len = String.get_uint16_be rt 0 in 573 + let extbuf, rt = split_str ~start:2 rt ext_len in 574 + cert, extbuf, rt 575 + in 576 + let exts = parse_list parse_certificate_ext extbuf [] in 577 + (Some (cert, exts), rest) 578 + 579 + let parse_certificate_ext_list_1_3_exn buf = 580 + let len = get_uint24_len ~off:0 buf in 581 + if String.length buf <> len + 3 then 582 + raise_trailing_bytes "certificates" 583 + else 584 + parse_list parse_certificate_ext_1_3_exn (shift buf 3) [] 585 + 586 + let parse_certificates_1_3_exn buf = 587 + let clen = String.get_uint8 buf 0 in 588 + let context, rt = split_str ~start:1 buf clen in 589 + let certs = parse_certificate_ext_list_1_3_exn rt in 590 + (context, certs) 591 + 592 + let parse_certificates_1_3 = catch @@ parse_certificates_1_3_exn 593 + 594 + let parse_certificate_types buf = 595 + let parsef buf = 596 + let byte = String.get_uint8 buf 0 in 597 + (int_to_client_certificate_type byte, shift buf 1) 598 + in 599 + let count = String.get_uint8 buf 0 in 600 + parse_count_list parsef (shift buf 1) [] count 601 + 602 + let parse_cas buf = 603 + let parsef buf = 604 + let length = String.get_uint16_be buf 0 in 605 + let name = String.sub buf 2 length in 606 + (Some name, shift buf (2 + length)) 607 + in 608 + let calength = String.get_uint16_be buf 0 in 609 + let cas, rt = split_str ~start:2 buf calength in 610 + (parse_list parsef cas [], rt) 611 + 612 + let parse_certificate_request_exn buf = 613 + let certificate_types, buf' = parse_certificate_types buf in 614 + let certificate_authorities, buf' = parse_cas buf' in 615 + if String.length buf' <> 0 then 616 + raise_trailing_bytes "certificate request" 617 + else 618 + (certificate_types, certificate_authorities) 619 + 620 + let parse_certificate_request = 621 + catch parse_certificate_request_exn 622 + 623 + let parse_certificate_request_1_2_exn buf = 624 + let certificate_types, buf' = parse_certificate_types buf in 625 + let sigs, buf' = parse_signature_algorithms buf' in 626 + let cas, buf' = parse_cas buf' in 627 + if String.length buf' <> 0 then 628 + raise_trailing_bytes "certificate request" 629 + else 630 + (certificate_types, sigs, cas) 631 + 632 + let parse_certificate_request_1_2 = 633 + catch parse_certificate_request_1_2_exn 634 + 635 + let parse_certificate_request_extension raw = 636 + let etype, len, buf = parse_ext raw in 637 + let data = match int_to_extension_type etype with 638 + | Some SIGNATURE_ALGORITHMS -> 639 + let algos, rt = parse_signature_algorithms buf in 640 + if String.length rt <> 0 then 641 + raise_trailing_bytes "signature algorithms" 642 + else 643 + `SignatureAlgorithms algos 644 + | Some CERTIFICATE_AUTHORITIES -> 645 + let cas, rt = parse_cas buf in 646 + if String.length rt <> 0 then 647 + raise_trailing_bytes "certificate authorities" 648 + else 649 + let cas = List.fold_left (fun cas buf -> 650 + match X509.Distinguished_name.decode_der buf with 651 + | Ok ca -> ca :: cas 652 + | Error _ -> cas) 653 + [] cas 654 + in 655 + `CertificateAuthorities (List.rev cas) 656 + | _ -> `UnknownExtension (etype, buf) 657 + in 658 + (Some data, shift raw (4 + len)) 659 + 660 + let parse_certificate_request_1_3_exn buf = 661 + let contextlen = String.get_uint8 buf 0 in 662 + let context, rt = 663 + if contextlen = 0 then 664 + None, shift buf 1 665 + else 666 + let ctx, rest = split_str ~start:1 buf contextlen in 667 + Some ctx, rest 668 + in 669 + let exts = parse_extensions parse_certificate_request_extension rt in 670 + (context, exts) 671 + 672 + let parse_certificate_request_1_3 = 673 + catch parse_certificate_request_1_3_exn 674 + 675 + let parse_dh_parameters = catch @@ fun raw -> 676 + let plength = String.get_uint16_be raw 0 in 677 + let dh_p = String.sub raw 2 plength in 678 + let buf = shift raw (2 + plength) in 679 + let glength = String.get_uint16_be buf 0 in 680 + let dh_g = String.sub buf 2 glength in 681 + let buf = shift buf (2 + glength) in 682 + let yslength = String.get_uint16_be buf 0 in 683 + let dh_Ys = String.sub buf 2 yslength in 684 + let buf = shift buf (2 + yslength) in 685 + let rawparams = String.sub raw 0 (plength + glength + yslength + 6) in 686 + ({ dh_p ; dh_g ; dh_Ys }, rawparams, buf) 687 + 688 + let parse_ec_parameters = catch @@ fun raw -> 689 + if String.get_uint8 raw 0 <> ec_curve_type_to_int NAMED_CURVE then 690 + raise_unknown "EC curve type" 691 + else 692 + match int_to_named_group (String.get_uint16_be raw 1) with 693 + | Some g -> 694 + begin match named_group_to_group g with 695 + | Some ((`X25519 | `P256 | `P384 | `P521) as g) -> 696 + let data_len = String.get_uint8 raw 3 in 697 + let d, rest = split_str ~start:4 raw data_len in 698 + g, d, String.sub raw 0 (data_len + 4), rest 699 + | _ -> raise_unknown "EC group" 700 + end 701 + | None -> raise_unknown "EC named group" 702 + 703 + let parse_digitally_signed_exn buf = 704 + let siglen = String.get_uint16_be buf 0 in 705 + if String.length buf <> siglen + 2 then 706 + raise_trailing_bytes "digitally signed" 707 + else 708 + String.sub buf 2 siglen 709 + 710 + let parse_digitally_signed = 711 + catch parse_digitally_signed_exn 712 + 713 + let parse_digitally_signed_1_2 = catch @@ fun buf -> 714 + match parse_signature_algorithm buf with 715 + | Some sig_alg -> 716 + let signature = parse_digitally_signed_exn (shift buf 2) in 717 + (sig_alg, signature) 718 + | None -> raise_unknown "hash or signature algorithm" 719 + 720 + let parse_session_ticket_extension raw = 721 + let etype, len, buf = parse_ext raw in 722 + let data = match int_to_extension_type etype with 723 + | Some EARLY_DATA -> 724 + if String.length buf <> 4 then 725 + raise_unknown "bad early_data extension in session ticket" 726 + else 727 + let size = String.get_int32_be buf 0 in 728 + `EarlyDataIndication size 729 + | _ -> `UnknownExtension (etype, buf) 730 + in 731 + (Some data, shift raw (4 + len)) 732 + 733 + let parse_session_ticket buf = 734 + let lifetime = String.get_int32_be buf 0 735 + and age_add = String.get_int32_be buf 4 736 + and nonce_len = String.get_uint8 buf 8 737 + in 738 + let nonce = String.sub buf 9 nonce_len in 739 + let ticket_len = String.get_uint16_be buf (9 + nonce_len) in 740 + let ticket, exts_buf = split_str ~start:(11 + nonce_len) buf ticket_len in 741 + let extensions = parse_extensions parse_session_ticket_extension exts_buf in 742 + { lifetime ; age_add ; nonce ; ticket ; extensions } 743 + 744 + let parse_client_dh_key_exchange_exn buf = 745 + let len = String.get_uint16_be buf 0 in 746 + if String.length buf <> len + 2 then 747 + raise_trailing_bytes "client key exchange" 748 + else 749 + String.sub buf 2 len 750 + 751 + let parse_client_dh_key_exchange = catch parse_client_dh_key_exchange_exn 752 + 753 + let parse_client_ec_key_exchange_exn buf = 754 + let len = String.get_uint8 buf 0 in 755 + if String.length buf <> len + 1 then 756 + raise_trailing_bytes "client key exchange" 757 + else 758 + String.sub buf 1 len 759 + 760 + let parse_client_ec_key_exchange = catch parse_client_ec_key_exchange_exn 761 + 762 + let parse_keyupdate buf = 763 + if String.length buf <> 1 then 764 + raise_trailing_bytes "key update" 765 + else 766 + match int_to_key_update_request_type (String.get_uint8 buf 0) with 767 + | Some y -> y 768 + | None -> raise_unknown "key update content" 769 + 770 + let parse_handshake_frame buf = 771 + if String.length buf < 4 then 772 + (None, buf) 773 + else 774 + let l = get_uint24_len ~off:1 buf in 775 + let hslen = l + 4 in 776 + if String.length buf >= hslen then 777 + let hs, rest = split_str buf hslen in 778 + (Some hs, rest) 779 + else 780 + (None, buf) 781 + 782 + let parse_handshake = catch @@ fun buf -> 783 + let typ = String.get_uint8 buf 0 in 784 + let handshake_type = int_to_handshake_type typ in 785 + let len = get_uint24_len ~off:1 buf in 786 + if String.length buf <> len + 4 then 787 + raise_trailing_bytes "handshake" 788 + else 789 + let payload = String.sub buf 4 len in 790 + match handshake_type with 791 + | Some HELLO_REQUEST -> 792 + if String.length payload = 0 then HelloRequest else raise_trailing_bytes "hello request" 793 + | Some CLIENT_HELLO -> parse_client_hello payload 794 + | Some SERVER_HELLO -> parse_server_hello payload 795 + | Some CERTIFICATE -> Certificate payload 796 + | Some CERTIFICATE_VERIFY -> CertificateVerify payload 797 + | Some SERVER_KEY_EXCHANGE -> ServerKeyExchange payload 798 + | Some SERVER_HELLO_DONE -> 799 + if String.length payload = 0 then ServerHelloDone else raise_trailing_bytes "server hello done" 800 + | Some CERTIFICATE_REQUEST -> CertificateRequest payload 801 + | Some CLIENT_KEY_EXCHANGE -> ClientKeyExchange payload 802 + | Some FINISHED -> Finished payload 803 + | Some ENCRYPTED_EXTENSIONS -> 804 + let ee = parse_extensions parse_encrypted_extension payload in 805 + EncryptedExtensions ee 806 + | Some KEY_UPDATE -> 807 + let ku = parse_keyupdate payload in 808 + KeyUpdate ku 809 + | Some SESSION_TICKET -> 810 + let ticket = parse_session_ticket payload in 811 + SessionTicket ticket 812 + | Some END_OF_EARLY_DATA -> 813 + EndOfEarlyData 814 + | Some _ 815 + | None -> raise_unknown @@ "handshake type" ^ string_of_int typ
+31
vendor/opam/tls/lib/reader.mli
··· 1 + 2 + val parse_version : string -> (Core.tls_version, [> `Decode of string ]) result 3 + val parse_any_version : string -> (Core.tls_any_version, [> `Decode of string ]) result 4 + val parse_record : string -> 5 + ([ `Record of (Core.tls_hdr * string) * string 6 + | `Fragment of string 7 + ], [> `Unexpected of [> `Content_type of int ] 8 + | `Protocol_version of [> `Unknown_record of int * int ] 9 + | `Record_overflow of int ]) result 10 + 11 + val parse_handshake_frame : string -> (string option * string) 12 + val parse_handshake : string -> (Core.tls_handshake, [> `Decode of string ]) result 13 + 14 + val parse_alert : string -> (Core.tls_alert, [> `Decode of string ]) result 15 + 16 + val parse_change_cipher_spec : string -> (unit, [> `Decode of string ]) result 17 + 18 + val parse_certificate_request : string -> (Packet.client_certificate_type list * string list, [> `Decode of string ]) result 19 + val parse_certificate_request_1_2 : string -> (Packet.client_certificate_type list * Core.signature_algorithm list * string list, [> `Decode of string ]) result 20 + val parse_certificate_request_1_3 : string -> (string option * Core.certificate_request_extension list, [> `Decode of string ]) result 21 + 22 + val parse_certificates : string -> (string list, [> `Decode of string ]) result 23 + val parse_certificates_1_3 : string -> (string * (string * 'a list) list, [> `Decode of string ]) result 24 + 25 + val parse_client_dh_key_exchange : string -> (string, [> `Decode of string ]) result 26 + val parse_client_ec_key_exchange : string -> (string, [> `Decode of string ]) result 27 + 28 + val parse_dh_parameters : string -> (Core.dh_parameters * string * string, [> `Decode of string ]) result 29 + val parse_ec_parameters : string -> ([ `X25519 | `P256 | `P384 | `P521 ] * string * string * string, [> `Decode of string ]) result 30 + val parse_digitally_signed : string -> (string, [> `Decode of string ]) result 31 + val parse_digitally_signed_1_2 : string -> (Core.signature_algorithm * string, [> `Decode of string ]) result
+352
vendor/opam/tls/lib/state.ml
··· 1 + (* Defines all high-level datatypes for the TLS library. It is opaque to clients 2 + of this library, and only used from within the library. *) 3 + 4 + open Core 5 + open Mirage_crypto 6 + 7 + type hmac_key = string 8 + 9 + (* initialisation vector style, depending on TLS version *) 10 + type iv_mode = 11 + | Iv of string (* traditional CBC (reusing last cipherblock) *) 12 + | Random_iv (* TLS 1.1 and higher explicit IV (we use random) *) 13 + 14 + type 'k cbc_cipher = (module Block.CBC with type key = 'k) 15 + type 'k cbc_state = { 16 + cipher : 'k cbc_cipher ; 17 + cipher_secret : 'k ; 18 + iv_mode : iv_mode ; 19 + hmac : Digestif.hash' ; 20 + hmac_secret : hmac_key 21 + } 22 + 23 + type nonce = string 24 + 25 + type 'k aead_cipher = (module AEAD with type key = 'k) 26 + type 'k aead_state = { 27 + cipher : 'k aead_cipher ; 28 + cipher_secret : 'k ; 29 + nonce : nonce ; 30 + explicit_nonce : bool ; (* RFC 7905: no explicit nonce, instead TLS 1.3 construction is adapted *) 31 + 32 + } 33 + 34 + (* state of a symmetric cipher *) 35 + type cipher_st = 36 + | CBC : 'k cbc_state -> cipher_st 37 + | AEAD : 'k aead_state -> cipher_st 38 + 39 + (* context of a TLS connection (both in and out has each one of these) *) 40 + type crypto_context = { 41 + sequence : int64 ; (* sequence number *) 42 + cipher_st : cipher_st ; (* cipher state *) 43 + } 44 + (* the raw handshake log we need to carry around *) 45 + type hs_log = string list 46 + 47 + type dh_secret = [ 48 + | `Finite_field of Mirage_crypto_pk.Dh.secret 49 + | `P256 of Mirage_crypto_ec.P256.Dh.secret 50 + | `P384 of Mirage_crypto_ec.P384.Dh.secret 51 + | `P521 of Mirage_crypto_ec.P521.Dh.secret 52 + | `X25519 of Mirage_crypto_ec.X25519.secret 53 + ] 54 + 55 + (* a collection of client and server verify bytes for renegotiation *) 56 + type reneg_params = string * string 57 + 58 + type common_session_data = { 59 + server_random : string ; (* 32 bytes random from the server hello *) 60 + client_random : string ; (* 32 bytes random from the client hello *) 61 + peer_certificate_chain : X509.Certificate.t list ; 62 + peer_certificate : X509.Certificate.t option ; 63 + trust_anchor : X509.Certificate.t option ; 64 + received_certificates : X509.Certificate.t list ; 65 + own_certificate : X509.Certificate.t list ; 66 + own_private_key : X509.Private_key.t option ; 67 + own_name : [`host] Domain_name.t option ; 68 + client_auth : bool ; 69 + master_secret : master_secret ; 70 + alpn_protocol : string option ; (* selected alpn protocol after handshake *) 71 + } 72 + 73 + type session_data = { 74 + common_session_data : common_session_data ; 75 + client_version : tls_any_version ; (* version in client hello (needed in RSA client key exchange) *) 76 + ciphersuite : Ciphersuite.ciphersuite ; 77 + group : group option ; 78 + renegotiation : reneg_params ; (* renegotiation data *) 79 + session_id : string ; 80 + extended_ms : bool ; 81 + tls_unique : string ; 82 + } 83 + 84 + (* state machine of the server *) 85 + type server_handshake_state = 86 + | AwaitClientHello (* initial state *) 87 + | AwaitClientHelloRenegotiate 88 + | AwaitClientCertificate_RSA of session_data * hs_log 89 + | AwaitClientCertificate_DHE of session_data * dh_secret * hs_log 90 + | AwaitClientKeyExchange_RSA of session_data * hs_log (* server hello done is sent, and RSA key exchange used, waiting for a client key exchange message *) 91 + | AwaitClientKeyExchange_DHE of session_data * dh_secret * hs_log (* server hello done is sent, and DHE_RSA key exchange used, waiting for client key exchange *) 92 + | AwaitClientCertificateVerify of session_data * crypto_context * crypto_context * hs_log 93 + | AwaitClientChangeCipherSpec of session_data * crypto_context * crypto_context * hs_log (* client key exchange received, next should be change cipher spec *) 94 + | AwaitClientChangeCipherSpecResume of session_data * crypto_context * string * hs_log (* resumption: next should be change cipher spec *) 95 + | AwaitClientFinished of session_data * hs_log (* change cipher spec received, next should be the finished including a hmac over all handshake packets *) 96 + | AwaitClientFinishedResume of session_data * string * hs_log (* change cipher spec received, next should be the finished including a hmac over all handshake packets *) 97 + | Established (* handshake successfully completed *) 98 + 99 + (* state machine of the client *) 100 + type client_handshake_state = 101 + | ClientInitial (* initial state *) 102 + | AwaitServerHello of client_hello * (group * dh_secret) list * hs_log (* client hello is sent, handshake_params are half-filled *) 103 + | AwaitServerHelloRenegotiate of session_data * client_hello * hs_log (* client hello is sent, handshake_params are half-filled *) 104 + | AwaitCertificate_RSA of session_data * hs_log (* certificate expected with RSA key exchange *) 105 + | AwaitCertificate_DHE of session_data * hs_log (* certificate expected with DHE key exchange *) 106 + | AwaitServerKeyExchange_DHE of session_data * hs_log (* server key exchange expected with DHE *) 107 + | AwaitCertificateRequestOrServerHelloDone of session_data * string * string * hs_log (* server hello done expected, client key exchange and premastersecret are ready *) 108 + | AwaitServerHelloDone of session_data * signature_algorithm list option * string * string * hs_log (* server hello done expected, client key exchange and premastersecret are ready *) 109 + | AwaitServerChangeCipherSpec of session_data * crypto_context * string * hs_log (* change cipher spec expected *) 110 + | AwaitServerChangeCipherSpecResume of session_data * crypto_context * crypto_context * hs_log (* change cipher spec expected *) 111 + | AwaitServerFinished of session_data * string * hs_log (* finished expected with a hmac over all handshake packets *) 112 + | AwaitServerFinishedResume of session_data * hs_log (* finished expected with a hmac over all handshake packets *) 113 + | Established (* handshake successfully completed *) 114 + 115 + type kdf = { 116 + secret : string ; 117 + cipher : Ciphersuite.ciphersuite13 ; 118 + hash : Digestif.hash' ; 119 + } 120 + 121 + (* TODO needs log of CH..CF for post-handshake auth *) 122 + (* TODO drop master_secret!? *) 123 + type session_data13 = { 124 + common_session_data13 : common_session_data ; 125 + ciphersuite13 : Ciphersuite.ciphersuite13 ; 126 + master_secret : kdf ; 127 + exporter_master_secret : string ; 128 + resumption_secret : string ; 129 + state : epoch_state ; 130 + resumed : bool ; 131 + client_app_secret : string ; 132 + server_app_secret : string ; 133 + } 134 + 135 + type client13_handshake_state = 136 + | AwaitServerHello13 of client_hello * (group * dh_secret) list * string (* this is for CH1 ~> HRR ~> CH2 <~ WAIT SH *) 137 + | AwaitServerEncryptedExtensions13 of session_data13 * string * string * string 138 + | AwaitServerCertificateRequestOrCertificate13 of session_data13 * string * string * string 139 + | AwaitServerCertificate13 of session_data13 * string * string * signature_algorithm list option * string 140 + | AwaitServerCertificateVerify13 of session_data13 * string * string * signature_algorithm list option * string 141 + | AwaitServerFinished13 of session_data13 * string * string * signature_algorithm list option * string 142 + | Established13 143 + 144 + type server13_handshake_state = 145 + | AwaitClientHelloHRR13 (* if we sent out HRR (also to-be-used for tls13-only) *) 146 + | AwaitClientCertificate13 of session_data13 * string * crypto_context * session_ticket option * string 147 + | AwaitClientCertificateVerify13 of session_data13 * string * crypto_context * session_ticket option * string 148 + | AwaitClientFinished13 of string * crypto_context * session_ticket option * string 149 + | AwaitEndOfEarlyData13 of string * crypto_context * crypto_context * session_ticket option * string 150 + | Established13 151 + 152 + type handshake_machina_state = 153 + | Client of client_handshake_state 154 + | Server of server_handshake_state 155 + | Client13 of client13_handshake_state 156 + | Server13 of server13_handshake_state 157 + 158 + (* state during a handshake, used in the handlers *) 159 + type handshake_state = { 160 + session : [ `TLS of session_data | `TLS13 of session_data13 ] list ; 161 + protocol_version : tls_version ; 162 + early_data_left : int32 ; 163 + machina : handshake_machina_state ; (* state machine state *) 164 + config : Config.config ; (* given config *) 165 + hs_fragment : string ; (* handshake messages can be fragmented, leftover from before *) 166 + } 167 + 168 + (* connection state: initially None, after handshake a crypto context *) 169 + type crypto_state = crypto_context option 170 + 171 + (* record consisting of a content type and a byte vector *) 172 + type record = Packet.content_type * string 173 + 174 + (* response returned by a handler *) 175 + type rec_resp = [ 176 + | `Change_enc of crypto_context (* either instruction to change the encryptor to the given one *) 177 + | `Change_dec of crypto_context (* either change the decryptor to the given one *) 178 + | `Record of record (* or a record which should be sent out *) 179 + ] 180 + 181 + (* return type of handshake handlers *) 182 + type handshake_return = handshake_state * rec_resp list 183 + 184 + (* Top level state, encapsulating the entire session. *) 185 + type state = { 186 + handshake : handshake_state ; (* the current handshake state *) 187 + decryptor : crypto_state ; (* the current decryption state *) 188 + encryptor : crypto_state ; (* the current encryption state *) 189 + fragment : string ; (* the leftover fragment from TCP fragmentation *) 190 + read_closed : bool ; 191 + write_closed : bool ; 192 + } 193 + 194 + type error = [ 195 + | `AuthenticationFailure of X509.Validation.validation_error 196 + | `NoConfiguredCiphersuite of Ciphersuite.ciphersuite list 197 + | `NoConfiguredVersions of tls_version list 198 + | `NoConfiguredSignatureAlgorithm of signature_algorithm list 199 + | `NoMatchingCertificateFound of string 200 + | `CouldntSelectCertificate 201 + ] 202 + 203 + let pp_error ppf = function 204 + | `AuthenticationFailure v -> 205 + Fmt.pf ppf "authentication failure: %a" X509.Validation.pp_validation_error v 206 + | `NoConfiguredCiphersuite cs -> 207 + Fmt.pf ppf "no configured ciphersuite: %a" 208 + Fmt.(list ~sep:(any ", ") Ciphersuite.pp_ciphersuite) cs 209 + | `NoConfiguredVersions vs -> 210 + Fmt.pf ppf "no configured version: %a" 211 + Fmt.(list ~sep:(any ", ") pp_tls_version) vs 212 + | `NoConfiguredSignatureAlgorithm sas -> 213 + Fmt.pf ppf "no configure signature algorithm: %a" 214 + Fmt.(list ~sep:(any ", ") pp_signature_algorithm) sas 215 + | `NoMatchingCertificateFound host -> 216 + Fmt.pf ppf "no matching certificate found for %s" host 217 + | `CouldntSelectCertificate -> Fmt.string ppf "couldn't select certificate" 218 + 219 + type fatal = [ 220 + | `Protocol_version of [ 221 + | `None_supported of tls_any_version list 222 + | `Unknown_record of int * int 223 + | `Bad_record of tls_any_version 224 + ] 225 + | `Unexpected of [ 226 + | `Content_type of int 227 + | `Message of string 228 + | `Handshake of tls_handshake 229 + ] 230 + | `Decode of string 231 + | `Handshake of [ 232 + | `Message of string 233 + | `Fragments 234 + | `BadDH of string 235 + | `BadECDH of Mirage_crypto_ec.error 236 + ] 237 + | `Bad_certificate of string 238 + | `Missing_extension of string 239 + | `Bad_mac 240 + | `Record_overflow of int 241 + | `Unsupported_extension 242 + | `Inappropriate_fallback 243 + | `No_application_protocol 244 + ] 245 + 246 + let pp_protocol_version ppf = function 247 + | `None_supported vs -> 248 + Fmt.pf ppf "none supported, client provided %a" 249 + Fmt.(list ~sep:(any ", ") pp_tls_any_version) vs 250 + | `Unknown_record (maj, min) -> 251 + Fmt.pf ppf "unknown record version %u.%u" maj min 252 + | `Bad_record v -> 253 + Fmt.pf ppf "bad record version %a" pp_tls_any_version v 254 + 255 + let pp_unexpected ppf = function 256 + | `Content_type c -> Fmt.pf ppf "content type %u" c 257 + | `Message msg -> Fmt.string ppf msg 258 + | `Handshake hs -> Fmt.pf ppf "handshake %a" pp_handshake hs 259 + 260 + let pp_handshake_error ppf = function 261 + | `Message msg -> Fmt.string ppf msg 262 + | `Fragments -> Fmt.string ppf "fragments are not empty" 263 + | `BadDH msg -> Fmt.pf ppf "bad DH %s" msg 264 + | `BadECDH e -> Fmt.pf ppf "bad ECDH %a" Mirage_crypto_ec.pp_error e 265 + 266 + let pp_fatal ppf = function 267 + | `Protocol_version e -> Fmt.pf ppf "version error: %a" pp_protocol_version e 268 + | `Unexpected p -> Fmt.pf ppf "unexpected: %a" pp_unexpected p 269 + | `Decode msg -> Fmt.pf ppf "decode error: %s" msg 270 + | `Handshake h -> Fmt.pf ppf "handshake error: %a" pp_handshake_error h 271 + | `Bad_certificate msg -> Fmt.pf ppf "bad certificate: %s" msg 272 + | `Missing_extension msg -> Fmt.pf ppf "missing extension: %s" msg 273 + | `Bad_mac -> Fmt.string ppf "MAC mismatch" 274 + | `Record_overflow n -> Fmt.pf ppf "record overflow %u" n 275 + | `Unsupported_extension -> Fmt.string ppf "unsupported extension" 276 + | `Inappropriate_fallback -> Fmt.string ppf "inappropriate fallback" 277 + | `No_application_protocol -> Fmt.string ppf "no application protocol" 278 + 279 + type failure = [ 280 + | `Error of error 281 + | `Fatal of fatal 282 + | `Alert of Packet.alert_type 283 + ] 284 + 285 + let pp_failure ppf = function 286 + | `Error e -> pp_error ppf e 287 + | `Fatal f -> pp_fatal ppf f 288 + | `Alert a -> Fmt.pf ppf "alert %s" (Packet.alert_type_to_string a) 289 + 290 + let common_data_to_epoch common is_server peer_name = 291 + let own_random, peer_random = 292 + if is_server then 293 + common.server_random, common.client_random 294 + else 295 + common.client_random, common.server_random 296 + in 297 + let epoch : epoch_data = 298 + { side = if is_server then `Server else `Client ; 299 + state = `Established ; 300 + protocol_version = `TLS_1_0 ; 301 + ciphersuite = `DHE_RSA_WITH_AES_256_CBC_SHA ; 302 + peer_random ; 303 + peer_certificate = common.peer_certificate ; 304 + peer_certificate_chain = common.peer_certificate_chain ; 305 + peer_name ; 306 + trust_anchor = common.trust_anchor ; 307 + own_random ; 308 + own_certificate = common.own_certificate ; 309 + own_private_key = common.own_private_key ; 310 + own_name = common.own_name ; 311 + received_certificates = common.received_certificates ; 312 + master_secret = common.master_secret ; 313 + exporter_master_secret = "" ; 314 + alpn_protocol = common.alpn_protocol ; 315 + session_id = "" ; 316 + extended_ms = false ; 317 + tls_unique = None ; 318 + } in 319 + epoch 320 + 321 + let epoch_of_session server peer_name protocol_version = function 322 + | `TLS (session : session_data) -> 323 + let epoch = common_data_to_epoch session.common_session_data server peer_name in 324 + { 325 + epoch with 326 + protocol_version = protocol_version ; 327 + ciphersuite = session.ciphersuite ; 328 + session_id = session.session_id ; 329 + extended_ms = session.extended_ms ; 330 + tls_unique = Some session.tls_unique ; 331 + } 332 + | `TLS13 (session : session_data13) -> 333 + let epoch : epoch_data = common_data_to_epoch session.common_session_data13 server peer_name in 334 + { 335 + epoch with 336 + protocol_version = protocol_version ; 337 + ciphersuite = (session.ciphersuite13 :> Ciphersuite.ciphersuite) ; 338 + extended_ms = true ; (* RFC 8446, Appendix D, last paragraph *) 339 + state = session.state ; 340 + exporter_master_secret = session.exporter_master_secret ; 341 + } 342 + 343 + let epoch_of_hs hs = 344 + let server = 345 + match hs.machina with 346 + | Client _ | Client13 _ -> false 347 + | Server _ | Server13 _ -> true 348 + and peer_name = Config.(hs.config.peer_name) 349 + in 350 + match hs.session with 351 + | [] -> None 352 + | session :: _ -> Some (epoch_of_session server peer_name hs.protocol_version session)
+40
vendor/opam/tls/lib/utils.ml
··· 1 + module List_set = struct 2 + let subset ?(compare = compare) l1 l2 = 3 + let rec loop xs ys = 4 + match (xs, ys) with 5 + | ([], _) -> true 6 + | (_, []) -> false 7 + | (x::xss, y::yss) -> 8 + match compare x y with 9 + | -1 -> false 10 + | 1 -> loop xs yss 11 + | _ -> loop xss yss in 12 + loop (List.sort compare l1) (List.sort compare l2) 13 + 14 + let is_proper_set l = 15 + let rec repeats = function 16 + | x::(y::_ as xs) -> x = y || repeats xs 17 + | _ -> false in 18 + not @@ repeats (List.sort compare l) 19 + end 20 + 21 + let rec map_find ~f = function 22 + | [] -> None 23 + | x::xs -> 24 + match f x with 25 + | None -> map_find ~f xs 26 + | Some _ as x' -> x' 27 + 28 + let init_and_last list = 29 + List.fold_right (fun x -> function 30 + | None -> Some ([], x) 31 + | Some (xs, y) -> Some (x::xs, y)) 32 + list None 33 + 34 + let rec first_match l1 = function 35 + | [] -> None 36 + | x::_ when List.mem x l1 -> Some x 37 + | _::xs -> first_match l1 xs 38 + 39 + let sub_equal ~off ~len v x = 40 + v = String.sub x off len
+491
vendor/opam/tls/lib/writer.ml
··· 1 + open Packet 2 + open Core 3 + 4 + let assemble_protocol_version_int buf off version = 5 + let major, minor = pair_of_tls_version version in 6 + Bytes.set_uint8 buf off major; 7 + Bytes.set_uint8 buf (off + 1) minor 8 + 9 + let assemble_protocol_version ?(buf= Bytes.create 2) version = 10 + assemble_protocol_version_int buf 0 version; 11 + Bytes.unsafe_to_string buf 12 + 13 + let assemble_any_protocol_version_into buf off version = 14 + let major, minor = pair_of_tls_any_version version in 15 + Bytes.set_uint8 buf off major; 16 + Bytes.set_uint8 buf (off + 1) minor 17 + 18 + let assemble_any_protocol_version version = 19 + let buf = Bytes.create 2 in 20 + assemble_any_protocol_version_into buf 0 version; 21 + Bytes.unsafe_to_string buf 22 + 23 + let assemble_hdr version (content_type, payload) = 24 + let buf = Bytes.create 5 in 25 + Bytes.set_uint8 buf 0 (content_type_to_int content_type); 26 + assemble_protocol_version_int buf 1 version; 27 + Bytes.set_uint16_be buf 3 (String.length payload); 28 + Bytes.unsafe_to_string buf ^ payload 29 + 30 + type len = One | Two | Three 31 + 32 + let assemble_list ?none_if_empty lenb f elements = 33 + let length body = 34 + match lenb with 35 + | One -> 36 + let l = Bytes.create 1 in 37 + Bytes.set_uint8 l 0 (String.length body) ; 38 + Bytes.unsafe_to_string l 39 + | Two -> 40 + let l = Bytes.create 2 in 41 + Bytes.set_uint16_be l 0 (String.length body) ; 42 + Bytes.unsafe_to_string l 43 + | Three -> 44 + let l = Bytes.create 3 in 45 + set_uint24_len ~off:0 l (String.length body) ; 46 + Bytes.unsafe_to_string l 47 + in 48 + let b es = String.concat "" (List.map f es) in 49 + let full es = 50 + let body = b es in 51 + length body ^ body 52 + in 53 + match none_if_empty with 54 + | Some _ -> (match elements with 55 + | [] -> "" 56 + | eles -> full eles) 57 + | None -> full elements 58 + 59 + let assemble_certificate c = 60 + let length = String.length c in 61 + let buf = Bytes.create 3 in 62 + set_uint24_len ~off:0 buf length; 63 + Bytes.unsafe_to_string buf ^ c 64 + 65 + let assemble_certificates cs = 66 + assemble_list Three assemble_certificate cs 67 + 68 + let assemble_compression_method m = 69 + String.make 1 (Char.unsafe_chr (compression_method_to_int m)) 70 + 71 + let assemble_compression_methods ms = 72 + assemble_list One assemble_compression_method ms 73 + 74 + let assemble_any_ciphersuite c = 75 + let buf = Bytes.create 2 in 76 + Bytes.set_uint16_be buf 0 (any_ciphersuite_to_int c); 77 + Bytes.unsafe_to_string buf 78 + 79 + let assemble_any_ciphersuites cs = 80 + assemble_list Two assemble_any_ciphersuite cs 81 + 82 + let assemble_ciphersuite c = 83 + let acs = Ciphersuite.ciphersuite_to_any_ciphersuite c in 84 + assemble_any_ciphersuite acs 85 + 86 + let assemble_hostname host = 87 + let host = Domain_name.to_string host in 88 + (* 8 bit hostname type; 16 bit length; value *) 89 + let vallength = String.length host in 90 + let buf = Bytes.create 3 in 91 + Bytes.set_uint8 buf 0 0; (* type, only 0 registered *) 92 + Bytes.set_uint16_be buf 1 vallength; 93 + Bytes.unsafe_to_string buf ^ host 94 + 95 + let assemble_hostnames hosts = 96 + assemble_list Two assemble_hostname hosts 97 + 98 + let assemble_hash_signature sigalg = 99 + let buf = Bytes.create 2 in 100 + Bytes.set_uint16_be buf 0 (signature_alg_to_int (to_signature_alg sigalg)) ; 101 + Bytes.unsafe_to_string buf 102 + 103 + let assemble_signature_algorithms s = 104 + assemble_list Two assemble_hash_signature s 105 + 106 + let assemble_certificate_types ts = 107 + let ass x = 108 + String.make 1 (Char.unsafe_chr (client_certificate_type_to_int x)) 109 + in 110 + assemble_list One ass ts 111 + 112 + let assemble_cas cas = 113 + let ass x = 114 + let buf = Bytes.create 2 in 115 + Bytes.set_uint16_be buf 0 (String.length x) ; 116 + Bytes.unsafe_to_string buf ^ x 117 + in 118 + assemble_list Two ass cas 119 + 120 + let assemble_certificate_request ts cas = 121 + assemble_certificate_types ts ^ assemble_cas cas 122 + 123 + let assemble_certificate_request_1_2 ts sigalgs cas = 124 + String.concat "" [ 125 + assemble_certificate_types ts; 126 + assemble_signature_algorithms sigalgs; 127 + assemble_cas cas 128 + ] 129 + 130 + let assemble_named_group g = 131 + let buf = Bytes.create 2 in 132 + Bytes.set_uint16_be buf 0 (named_group_to_int g); 133 + Bytes.unsafe_to_string buf 134 + 135 + let assemble_group g = 136 + assemble_named_group (group_to_named_group g) 137 + 138 + let assemble_supported_groups groups = 139 + assemble_list Two assemble_named_group groups 140 + 141 + let assemble_keyshare_entry (ng, ks) = 142 + let g = assemble_named_group ng in 143 + let l = Bytes.create 2 in 144 + Bytes.set_uint16_be l 0 (String.length ks) ; 145 + String.concat "" [ g ; Bytes.unsafe_to_string l ; ks ] 146 + 147 + let assemble_psk_id (id, age) = 148 + let id_len = Bytes.create 2 in 149 + Bytes.set_uint16_be id_len 0 (String.length id) ; 150 + let age_buf = Bytes.create 4 in 151 + Bytes.set_int32_be age_buf 0 age ; 152 + String.concat "" [ Bytes.unsafe_to_string id_len ; id ; Bytes.unsafe_to_string age_buf ] 153 + 154 + let assemble_binder b = 155 + let b_len = String.make 1 (Char.unsafe_chr (String.length b)) in 156 + b_len ^ b 157 + 158 + let assemble_client_psks psks = 159 + let ids, binders = List.split psks in 160 + let ids_buf = assemble_list Two assemble_psk_id ids in 161 + let binders_buf = assemble_list Two assemble_binder binders in 162 + ids_buf ^ binders_buf 163 + 164 + let assemble_alpn_protocol p = 165 + let buf = String.make 1 (Char.unsafe_chr (String.length p)) in 166 + buf ^ p 167 + 168 + let assemble_alpn_protocols protocols = 169 + assemble_list Two assemble_alpn_protocol protocols 170 + 171 + let assemble_supported_versions vs = 172 + assemble_list One assemble_any_protocol_version vs 173 + 174 + let assemble_extension = function 175 + | `SecureRenegotiation x -> 176 + let buf = String.make 1 (Char.unsafe_chr (String.length x)) in 177 + (buf ^ x, RENEGOTIATION_INFO) 178 + | `ExtendedMasterSecret -> ("", EXTENDED_MASTER_SECRET) 179 + | `ECPointFormats -> 180 + (* a list of point formats, we support type 0 = uncompressed unconditionally *) 181 + let data = Bytes.make 2 '\x00' in 182 + Bytes.set_uint8 data 0 1; 183 + (Bytes.unsafe_to_string data, EC_POINT_FORMATS) 184 + | _ -> invalid_arg "unknown extension" 185 + 186 + let assemble_cookie c = 187 + let l = Bytes.create 2 in 188 + Bytes.set_uint16_be l 0 (String.length c) ; 189 + Bytes.unsafe_to_string l ^ c 190 + 191 + let assemble_psk_key_exchange_mode mode = 192 + String.make 1 (Char.unsafe_chr (psk_key_exchange_mode_to_int mode)) 193 + 194 + let assemble_psk_key_exchange_modes modes = 195 + assemble_list One assemble_psk_key_exchange_mode modes 196 + 197 + let assemble_ext (pay, typ) = 198 + let buf = Bytes.create 4 in 199 + Bytes.set_uint16_be buf 0 (extension_type_to_int typ); 200 + Bytes.set_uint16_be buf 2 (String.length pay); 201 + Bytes.unsafe_to_string buf ^ pay 202 + 203 + let assemble_extensions ?none_if_empty assemble_e es = 204 + assemble_list ?none_if_empty Two assemble_e es 205 + 206 + let assemble_ca ca = 207 + let lenbuf = Bytes.create 2 in 208 + let data = X509.Distinguished_name.encode_der ca in 209 + Bytes.set_uint16_be lenbuf 0 (String.length data) ; 210 + Bytes.unsafe_to_string lenbuf ^ data 211 + 212 + let assemble_certificate_authorities cas = 213 + assemble_list Two assemble_ca cas 214 + 215 + let assemble_certificate_request_extension e = 216 + assemble_ext @@ match e with 217 + | `SignatureAlgorithms s -> 218 + (assemble_signature_algorithms s, SIGNATURE_ALGORITHMS) 219 + | `CertificateAuthorities cas -> 220 + (assemble_certificate_authorities cas, CERTIFICATE_AUTHORITIES) 221 + | _ -> invalid_arg "unknown extension" 222 + 223 + let assemble_certificate_request_1_3 ?(context = "") exts = 224 + let clen = String.make 1 (Char.unsafe_chr (String.length context)) in 225 + let exts = assemble_extensions assemble_certificate_request_extension exts in 226 + String.concat "" [ clen ; context ; exts ] 227 + 228 + let assemble_client_extension e = 229 + assemble_ext @@ match e with 230 + | `SupportedGroups groups -> 231 + (assemble_supported_groups groups, SUPPORTED_GROUPS) 232 + | `Hostname name -> (assemble_hostnames [name], SERVER_NAME) 233 + | `Padding x -> (String.make x '\x00', PADDING) 234 + | `SignatureAlgorithms s -> 235 + (assemble_signature_algorithms s, SIGNATURE_ALGORITHMS) 236 + | `ALPN protocols -> 237 + (assemble_alpn_protocols protocols, APPLICATION_LAYER_PROTOCOL_NEGOTIATION) 238 + | `KeyShare ks -> 239 + (assemble_list Two assemble_keyshare_entry ks, KEY_SHARE) 240 + | `PreSharedKeys ids -> 241 + (assemble_client_psks ids, PRE_SHARED_KEY) 242 + | `EarlyDataIndication -> 243 + ("", EARLY_DATA) 244 + | `SupportedVersions vs -> 245 + (assemble_supported_versions vs, SUPPORTED_VERSIONS) 246 + | `PostHandshakeAuthentication -> 247 + ("", POST_HANDSHAKE_AUTH) 248 + | `Cookie c -> 249 + (assemble_cookie c, COOKIE) 250 + | `PskKeyExchangeModes modes -> 251 + (assemble_psk_key_exchange_modes modes, PSK_KEY_EXCHANGE_MODES) 252 + | x -> assemble_extension x 253 + 254 + let assemble_server_extension e = 255 + assemble_ext @@ match e with 256 + | `Hostname -> ("", SERVER_NAME) 257 + | `ALPN protocol -> 258 + (assemble_alpn_protocols [protocol], APPLICATION_LAYER_PROTOCOL_NEGOTIATION) 259 + | `KeyShare (g, ks) -> 260 + let ng = group_to_named_group g in 261 + (assemble_keyshare_entry (ng, ks), KEY_SHARE) 262 + | `PreSharedKey id -> 263 + let data = Bytes.create 2 in 264 + Bytes.set_uint16_be data 0 id ; 265 + (Bytes.unsafe_to_string data, PRE_SHARED_KEY) 266 + | `SelectedVersion v -> (assemble_protocol_version v, SUPPORTED_VERSIONS) 267 + | x -> assemble_extension x 268 + 269 + let assemble_encrypted_extension e = 270 + assemble_ext @@ match e with 271 + | `Hostname -> ("", SERVER_NAME) 272 + | `ALPN protocol -> 273 + (assemble_alpn_protocols [protocol], APPLICATION_LAYER_PROTOCOL_NEGOTIATION) 274 + | `SupportedGroups groups -> 275 + (assemble_supported_groups (List.map group_to_named_group groups), SUPPORTED_GROUPS) 276 + | `EarlyDataIndication -> ("", EARLY_DATA) 277 + | _ -> invalid_arg "unknown extension" 278 + 279 + let assemble_retry_extension e = 280 + assemble_ext @@ match e with 281 + | `SelectedGroup g -> (assemble_group g, KEY_SHARE) 282 + | `Cookie c -> (assemble_cookie c, COOKIE) 283 + | `SelectedVersion v -> (assemble_protocol_version v, SUPPORTED_VERSIONS) 284 + | `UnknownExtension _ -> invalid_arg "unknown retry extension" 285 + 286 + let assemble_cert_ext (certificate, extensions) = 287 + let cert = assemble_certificate certificate 288 + and exts = assemble_list Two assemble_server_extension extensions 289 + in 290 + cert ^ exts 291 + 292 + let assemble_certs_exts cs = 293 + assemble_list Three assemble_cert_ext cs 294 + 295 + let assemble_certificates_1_3 context certs = 296 + let l = String.make 1 (Char.unsafe_chr (String.length context)) in 297 + String.concat "" [ l ; context ; assemble_certs_exts (List.map (fun c -> c, []) certs) ] 298 + 299 + let assemble_sid sid = 300 + match sid with 301 + | None -> String.make 1 '\x00' 302 + | Some s -> String.make 1 (Char.unsafe_chr (String.length s)) ^ s 303 + 304 + let assemble_client_hello (cl : client_hello) : string = 305 + let version = match cl.client_version with 306 + | `TLS_1_3 -> `TLS_1_2 (* keep 0x03 0x03 on wire *) 307 + | x -> x 308 + in 309 + let v = assemble_any_protocol_version version in 310 + let sid = assemble_sid cl.sessionid in 311 + let css = assemble_any_ciphersuites cl.ciphersuites in 312 + (* compression methods, completely useless *) 313 + let cms = assemble_compression_methods [NULL] in 314 + let bbuf = String.concat "" [ v ; cl.client_random ; sid ; css ; cms ] in 315 + let extensions = assemble_extensions ~none_if_empty:true assemble_client_extension cl.extensions in 316 + (* some widely deployed firewalls drop ClientHello messages which are 317 + > 256 and < 511 byte, insert PADDING extension for these *) 318 + (* from draft-ietf-tls-padding-00: 319 + As an example, consider a client that wishes to avoid sending a 320 + ClientHello with a record size between 256 and 511 bytes (inclusive). 321 + This case is considered because at least one TLS implementation is 322 + known to hang the connection when such a ClientHello record is 323 + received. 324 + 325 + After building a ClientHello as normal, the client can add four to 326 + the length (to account for the "msg_type" and "length" fields of the 327 + handshake protocol) and test whether the resulting length falls into 328 + that range. If it does, a padding extension can be added in order to 329 + push the length to (at least) 512 bytes. *) 330 + let extrapadding = 331 + (* since PreSharedKeys _must_ be the last extension, don't bother padding 332 + when it is present. rationale from ietf-tls WG 333 + "Padding extension and 0-RTT" thread (2016-10-30) *) 334 + if List.exists (function `PreSharedKeys _ -> true | _ -> false) cl.extensions then 335 + "" 336 + else 337 + let buflen = String.length bbuf + String.length extensions + 4 (* see above, header *) in 338 + if buflen >= 256 && buflen <= 511 then 339 + match String.length extensions with 340 + | 0 -> (* need to construct a 2 byte extension length as well *) 341 + let l = 512 (* desired length *) - 2 (* extension length *) - 4 (* padding extension header *) - buflen in 342 + let l = max l 0 in (* negative size is not good *) 343 + let padding = assemble_client_extension (`Padding l) in 344 + let extension_length = Bytes.create 2 in 345 + Bytes.set_uint16_be extension_length 0 (String.length padding); 346 + Bytes.unsafe_to_string extension_length ^ padding 347 + | _ -> 348 + let l = 512 - 4 (* padding extension header *) - buflen in 349 + let l = max l 0 in 350 + let padding = assemble_client_extension (`Padding l) in 351 + (* extensions include the 16 bit extension length field *) 352 + let elen = String.length extensions + String.length padding - 2 (* the 16 bit length field *) in 353 + Bytes.set_uint16_be (Bytes.unsafe_of_string extensions) 0 elen; 354 + padding 355 + else 356 + "" 357 + in 358 + String.concat "" [ bbuf ; extensions ; extrapadding ] 359 + 360 + let assemble_server_hello (sh : server_hello) : string = 361 + let version, exts = match sh.server_version with 362 + | `TLS_1_3 -> `TLS_1_2, `SelectedVersion `TLS_1_3 :: sh.extensions 363 + | x -> x, sh.extensions 364 + in 365 + let v = assemble_protocol_version version in 366 + let sid = assemble_sid sh.sessionid in 367 + let cs = assemble_ciphersuite sh.ciphersuite in 368 + (* useless compression method *) 369 + let cm = assemble_compression_method NULL in 370 + let extensions = assemble_extensions ~none_if_empty:true assemble_server_extension exts in 371 + String.concat "" [ v ; sh.server_random ; sid ; cs ; cm ; extensions ] 372 + 373 + let assemble_dh_parameters p = 374 + let plen, glen, yslen = (String.length p.dh_p, String.length p.dh_g, String.length p.dh_Ys) in 375 + let buf = Bytes.create (2 + 2 + 2 + plen + glen + yslen) in 376 + Bytes.set_uint16_be buf 0 plen; 377 + Bytes.blit_string p.dh_p 0 buf 2 plen; 378 + Bytes.set_uint16_be buf (2 + plen) glen; 379 + Bytes.blit_string p.dh_g 0 buf (4 + plen) glen; 380 + Bytes.set_uint16_be buf (4 + plen + glen) yslen; 381 + Bytes.blit_string p.dh_Ys 0 buf (6 + plen + glen) yslen; 382 + Bytes.unsafe_to_string buf 383 + 384 + let assemble_ec_parameters named_curve point = 385 + let hdr = Bytes.create 4 in 386 + Bytes.set_uint8 hdr 0 (ec_curve_type_to_int NAMED_CURVE); 387 + Bytes.set_uint16_be hdr 1 (named_group_to_int (group_to_named_group named_curve)); 388 + Bytes.set_uint8 hdr 3 (String.length point); 389 + Bytes.unsafe_to_string hdr ^ point 390 + 391 + let assemble_digitally_signed signature = 392 + let lenbuf = Bytes.create 2 in 393 + Bytes.set_uint16_be lenbuf 0 (String.length signature); 394 + Bytes.unsafe_to_string lenbuf ^ signature 395 + 396 + let assemble_digitally_signed_1_2 sigalg signature = 397 + (assemble_hash_signature sigalg) ^ (assemble_digitally_signed signature) 398 + 399 + let assemble_session_ticket_extension e = 400 + assemble_ext @@ match e with 401 + | `EarlyDataIndication max -> 402 + let buf = Bytes.create 4 in 403 + Bytes.set_int32_be buf 0 max ; 404 + (Bytes.unsafe_to_string buf, EARLY_DATA) 405 + | _ -> invalid_arg "unknown extension" 406 + 407 + let assemble_session_ticket (se : session_ticket) = 408 + let buf = Bytes.create 9 in 409 + Bytes.set_int32_be buf 0 se.lifetime ; 410 + Bytes.set_int32_be buf 4 se.age_add ; 411 + Bytes.set_uint8 buf 8 (String.length se.nonce) ; 412 + let ticketlen = Bytes.create 2 in 413 + Bytes.set_uint16_be ticketlen 0 (String.length se.ticket) ; 414 + let exts = assemble_extensions assemble_session_ticket_extension se.extensions in 415 + String.concat "" [ Bytes.unsafe_to_string buf ; se.nonce ; Bytes.unsafe_to_string ticketlen ; se.ticket ; exts ] 416 + 417 + let assemble_client_dh_key_exchange kex = 418 + let len = String.length kex in 419 + let buf = Bytes.create (len + 2) in 420 + Bytes.set_uint16_be buf 0 len; 421 + Bytes.blit_string kex 0 buf 2 len; 422 + Bytes.unsafe_to_string buf 423 + 424 + let assemble_client_ec_key_exchange kex = 425 + let len = String.length kex in 426 + let buf = Bytes.create (len + 1) in 427 + Bytes.set_uint8 buf 0 len; 428 + Bytes.blit_string kex 0 buf 1 len; 429 + Bytes.unsafe_to_string buf 430 + 431 + let assemble_hello_retry_request hrr = 432 + let exts = `SelectedGroup hrr.selected_group :: hrr.extensions in 433 + let version, exts = match hrr.retry_version with 434 + | `TLS_1_3 -> `TLS_1_2, `SelectedVersion `TLS_1_3 :: exts 435 + | x -> x, exts 436 + in 437 + let v = assemble_protocol_version version in 438 + let sid = assemble_sid hrr.sessionid in 439 + let cs = assemble_ciphersuite (hrr.ciphersuite :> Ciphersuite.ciphersuite) in 440 + (* useless compression method *) 441 + let cm = String.make 1 '\x00' in 442 + let extensions = assemble_extensions ~none_if_empty:true assemble_retry_extension exts in 443 + String.concat "" [ v ; helloretryrequest ; sid ; cs ; cm ; extensions ] 444 + 445 + let assemble_hs typ len = 446 + let buf = Bytes.create 4 in 447 + Bytes.set_uint8 buf 0 (handshake_type_to_int typ); 448 + set_uint24_len ~off:1 buf len; 449 + Bytes.unsafe_to_string buf 450 + 451 + let assemble_message_hash len = 452 + assemble_hs MESSAGE_HASH len 453 + 454 + let assemble_key_update req = 455 + String.make 1 (Char.unsafe_chr (key_update_request_type_to_int req)) 456 + 457 + let assemble_handshake hs = 458 + let (payload, payload_type) = 459 + match hs with 460 + | ClientHello ch -> (assemble_client_hello ch, CLIENT_HELLO) 461 + | ServerHello sh -> (assemble_server_hello sh, SERVER_HELLO) 462 + | HelloRetryRequest hr -> (assemble_hello_retry_request hr, SERVER_HELLO) 463 + | Certificate cs -> (cs, CERTIFICATE) 464 + | CertificateRequest cr -> (cr, CERTIFICATE_REQUEST) 465 + | CertificateVerify c -> (c, CERTIFICATE_VERIFY) 466 + | ServerKeyExchange kex -> (kex, SERVER_KEY_EXCHANGE) 467 + | ClientKeyExchange kex -> (kex, CLIENT_KEY_EXCHANGE) 468 + | ServerHelloDone -> ("", SERVER_HELLO_DONE) 469 + | HelloRequest -> ("", HELLO_REQUEST) 470 + | Finished fs -> (fs, FINISHED) 471 + | SessionTicket st -> (assemble_session_ticket st, SESSION_TICKET) 472 + | EncryptedExtensions ee -> 473 + let cs = assemble_extensions assemble_encrypted_extension ee in 474 + (cs, ENCRYPTED_EXTENSIONS) 475 + | KeyUpdate req -> 476 + let cs = assemble_key_update req in 477 + (cs, KEY_UPDATE) 478 + | EndOfEarlyData -> ("", END_OF_EARLY_DATA) 479 + in 480 + let pay_len = String.length payload in 481 + let buf = assemble_hs payload_type pay_len in 482 + buf ^ payload 483 + 484 + let assemble_alert ?(level = Packet.FATAL) typ = 485 + let buf = Bytes.create 2 in 486 + Bytes.set_uint8 buf 1 (alert_type_to_int typ); 487 + Bytes.set_uint8 buf 0 (alert_level_to_int level) ; 488 + Bytes.unsafe_to_string buf 489 + 490 + let assemble_change_cipher_spec = 491 + String.make 1 '\x01'
+34
vendor/opam/tls/lib/writer.mli
··· 1 + 2 + val assemble_protocol_version : ?buf:bytes -> Core.tls_version -> string 3 + 4 + val assemble_handshake : Core.tls_handshake -> string 5 + 6 + val assemble_message_hash : int -> string 7 + 8 + val assemble_hdr : Core.tls_version -> (Packet.content_type * string) -> string 9 + 10 + val assemble_alert : ?level:Packet.alert_level -> Packet.alert_type -> string 11 + 12 + val assemble_change_cipher_spec : string 13 + 14 + val assemble_dh_parameters : Core.dh_parameters -> string 15 + 16 + val assemble_ec_parameters : Core.group -> string -> string 17 + 18 + val assemble_client_dh_key_exchange : string -> string 19 + 20 + val assemble_client_ec_key_exchange : string -> string 21 + 22 + val assemble_digitally_signed : string -> string 23 + 24 + val assemble_digitally_signed_1_2 : Core.signature_algorithm -> string -> string 25 + 26 + val assemble_certificate_request : Packet.client_certificate_type list -> string list -> string 27 + 28 + val assemble_certificate_request_1_2 : Packet.client_certificate_type list -> Core.signature_algorithm list -> string list -> string 29 + 30 + val assemble_certificate_request_1_3 : ?context:string -> Core.certificate_request_extension list -> string 31 + 32 + val assemble_certificates : string list -> string 33 + 34 + val assemble_certificates_1_3 : string -> string list -> string
+5
vendor/opam/tls/lwt/dune
··· 1 + (library 2 + (name tls_lwt) 3 + (public_name tls-lwt) 4 + (wrapped false) 5 + (libraries tls lwt lwt.unix ptime.clock.os mirage-crypto-rng.unix))
+69
vendor/opam/tls/lwt/examples/dune
··· 1 + (library 2 + (name ex_common) 3 + (libraries lwt lwt.unix tls tls-lwt cmdliner fmt.cli logs.fmt fmt.tty logs.cli) 4 + (modules ex_common)) 5 + 6 + (executable 7 + (name starttls_server) 8 + (modules starttls_server) 9 + (libraries tls-lwt lwt.unix ex_common)) 10 + 11 + (executable 12 + (name echo_server) 13 + (modules echo_server) 14 + (libraries tls-lwt lwt.unix ex_common)) 15 + 16 + (executable 17 + (name echo_server_sni) 18 + (modules echo_server_sni) 19 + (libraries tls-lwt lwt.unix ex_common)) 20 + 21 + (executable 22 + (name echo_server_alpn) 23 + (modules echo_server_alpn) 24 + (libraries tls-lwt lwt.unix ex_common)) 25 + 26 + (executable 27 + (name echo_client) 28 + (modules echo_client) 29 + (libraries tls-lwt lwt.unix ex_common)) 30 + 31 + (executable 32 + (name echo_client_alpn) 33 + (modules echo_client_alpn) 34 + (libraries tls-lwt lwt.unix ex_common)) 35 + 36 + (executable 37 + (name test_server) 38 + (modules test_server) 39 + (libraries tls-lwt lwt.unix ex_common)) 40 + 41 + (executable 42 + (name test_client) 43 + (modules test_client) 44 + (libraries tls-lwt lwt.unix ex_common)) 45 + 46 + (executable 47 + (name tls_over_tls) 48 + (modules tls_over_tls) 49 + (libraries tls-lwt lwt lwt.unix ex_common)) 50 + 51 + (executable 52 + (name http_client) 53 + (modules http_client) 54 + (libraries tls-lwt lwt.unix ex_common)) 55 + 56 + (executable 57 + (name fuzz_server) 58 + (modules fuzz_server) 59 + (libraries tls-lwt lwt.unix ex_common)) 60 + 61 + (executable 62 + (name resume_client) 63 + (modules resume_client) 64 + (libraries tls-lwt lwt.unix ex_common)) 65 + 66 + (executable 67 + (name resume_echo_server) 68 + (modules resume_echo_server) 69 + (libraries randomconv tls-lwt lwt.unix ex_common))
+73
vendor/opam/tls/lwt/examples/echo_client.ml
··· 1 + 2 + open Ex_common 3 + open Lwt 4 + 5 + let cached_session : Tls.Core.epoch_data = 6 + let hex = Ohex.decode in 7 + { 8 + Tls.Core.side = `Client ; 9 + protocol_version = `TLS_1_3 ; 10 + ciphersuite = `DHE_RSA_WITH_AES_128_GCM_SHA256 ; 11 + peer_random = hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; 12 + peer_certificate = None ; 13 + peer_certificate_chain = [] ; 14 + peer_name = None ; 15 + trust_anchor = None ; 16 + received_certificates = [] ; 17 + own_random = hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; 18 + own_certificate = [] ; 19 + own_private_key = None ; 20 + own_name = None ; 21 + master_secret = hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; 22 + exporter_master_secret = "" ; 23 + session_id = "" ; 24 + extended_ms = true ; 25 + alpn_protocol = None ; 26 + state = `Established ; 27 + tls_unique = None ; 28 + } 29 + 30 + let echo_client ?ca hostname port = 31 + let open Lwt_io in 32 + auth ?ca () >>= fun authenticator -> 33 + X509_lwt.private_of_pems 34 + ~cert:server_cert 35 + ~priv_key:server_key >>= fun certificate -> 36 + Tls_lwt.connect_ext 37 + (get_ok Tls.Config.(client ~authenticator ~cached_session ~certificates:(`Single certificate) ~ciphers:Ciphers.supported ())) 38 + (hostname, port) >>= fun (ic, oc) -> 39 + Lwt.join [ 40 + lines ic |> Lwt_stream.iter_s (printf "+ %s\n%!") ; 41 + lines stdin |> Lwt_stream.iter_s (write_line oc) 42 + ] 43 + 44 + let jump _ port host ca = 45 + try 46 + Lwt_main.run (echo_client ?ca host port) 47 + with 48 + | Tls_lwt.Tls_alert alert as exn -> 49 + print_alert "remote end" alert ; raise exn 50 + | Tls_lwt.Tls_failure alert as exn -> 51 + print_fail "our end" alert ; raise exn 52 + 53 + open Cmdliner 54 + 55 + let port = 56 + let doc = "Port to connect to" in 57 + Arg.(value & opt int 443 & info [ "port" ] ~doc) 58 + 59 + let host = 60 + let doc = "Host to connect to" in 61 + Arg.(value & opt string "" & info [ "host" ] ~doc) 62 + 63 + let trust = 64 + let doc = "Trust anchor" in 65 + Arg.(value & opt (some string) None & info [ "trust" ] ~doc) 66 + 67 + let cmd = 68 + let term = Term.(const jump $ setup_log $ port $ host $ trust) 69 + and info = Cmd.info "echo_client" ~version:"%%VERSION_NUM%%" 70 + in 71 + Cmd.v info term 72 + 73 + let () = exit (Cmd.eval cmd)
+22
vendor/opam/tls/lwt/examples/echo_client_alpn.ml
··· 1 + 2 + open Ex_common 3 + open Lwt 4 + 5 + let echo_client host port = 6 + let open Lwt_io in 7 + let port = int_of_string port in 8 + let authenticator = null_auth in 9 + Tls_lwt.Unix.connect 10 + (get_ok Tls.Config.(client ~authenticator ~alpn_protocols:["http/1.1"; "h2"] ())) 11 + (host, port) >>= fun t -> 12 + match Tls_lwt.Unix.epoch t with 13 + | Error () -> printl "Error" 14 + | Ok epoch -> ( 15 + match epoch.Tls.Core.alpn_protocol with 16 + | None -> printl "No protocol selected" 17 + | Some protocol -> printl ("Selected protocol: " ^ protocol) 18 + ) 19 + >>= fun () -> Tls_lwt.Unix.close t 20 + 21 + let () = 22 + Lwt_main.run (echo_client "127.0.0.1" "4433")
+75
vendor/opam/tls/lwt/examples/echo_server.ml
··· 1 + open Lwt 2 + open Ex_common 3 + 4 + let string_of_unix_err err f p = 5 + Printf.sprintf "Unix_error (%s, %s, %s)" 6 + (Unix.error_message err) f p 7 + 8 + let serve_ssl port callback = 9 + 10 + let tag = "server" in 11 + 12 + X509_lwt.private_of_pems 13 + ~cert:server_cert 14 + ~priv_key:server_key >>= fun cert -> 15 + 16 + let server_s () = 17 + let open Lwt_unix in 18 + let s = socket PF_INET SOCK_STREAM 0 in 19 + setsockopt s SO_REUSEADDR true ; 20 + bind s (ADDR_INET (Unix.inet_addr_any, port)) >|= fun () -> 21 + listen s 10 ; 22 + s in 23 + 24 + let handle channels addr = 25 + async @@ fun () -> 26 + Lwt.catch (fun () -> callback channels addr >>= fun () -> yap ~tag "<- handler done") 27 + (function 28 + | Tls_lwt.Tls_alert a -> 29 + yap ~tag @@ "handler: " ^ Tls.Packet.alert_type_to_string a 30 + | Tls_lwt.Tls_failure a -> 31 + yap ~tag @@ "handler: " ^ Tls.Engine.string_of_failure a 32 + | Unix.Unix_error (e, f, p) -> 33 + yap ~tag @@ "handler: " ^ (string_of_unix_err e f p) 34 + | _exn -> yap ~tag "handler: exception") 35 + in 36 + 37 + yap ~tag ("-> start @ " ^ string_of_int port) >>= fun () -> 38 + let rec loop s = 39 + let authenticator = null_auth in 40 + let config = get_ok (Tls.Config.server ~version:(`TLS_1_0, `TLS_1_3) ~ciphers:Tls.Config.Ciphers.supported ~reneg:true ~certificates:(`Single cert) ~authenticator ()) in 41 + (Lwt.catch 42 + (fun () -> Tls_lwt.accept_ext config s >|= fun r -> `R r) 43 + (function 44 + | Unix.Unix_error (e, f, p) -> return (`L (string_of_unix_err e f p)) 45 + | Tls_lwt.Tls_alert a -> return (`L (Tls.Packet.alert_type_to_string a)) 46 + | Tls_lwt.Tls_failure f -> return (`L (Tls.Engine.string_of_failure f)) 47 + | exn -> return (`L ("loop: exception: " ^ Printexc.to_string exn)))) >>= function 48 + | `R (channels, addr) -> 49 + yap ~tag "-> connect" >>= fun () -> ( handle channels addr ; loop s ) 50 + | `L (msg) -> 51 + yap ~tag ("server socket: " ^ msg) >>= fun () -> loop s 52 + in 53 + server_s () >>= fun s -> 54 + loop s 55 + 56 + let echo_server _ port = 57 + Lwt_main.run ( 58 + serve_ssl port @@ fun (ic, oc) _addr -> 59 + lines ic |> Lwt_stream.iter_s (fun line -> 60 + yap ~tag:"handler" ("+ " ^ line) >>= fun () -> 61 + Lwt_io.write_line oc line)) 62 + 63 + open Cmdliner 64 + 65 + let port = 66 + let doc = "Port to connect to" in 67 + Arg.(value & opt int 4433 & info [ "port" ] ~doc) 68 + 69 + let cmd = 70 + let term = Term.(ret (const echo_server $ setup_log $ port)) 71 + and info = Cmd.info "echo_server" ~version:"%%VERSION_NUM%%" 72 + in 73 + Cmd.v info term 74 + 75 + let () = exit (Cmd.eval cmd)
+68
vendor/opam/tls/lwt/examples/echo_server_alpn.ml
··· 1 + 2 + open Lwt 3 + open Ex_common 4 + 5 + let split_on_char sep s = 6 + let r = ref [] in 7 + let j = ref (String.length s) in 8 + for i = String.length s - 1 downto 0 do 9 + if s.[i] = sep then begin 10 + r := String.sub s (i + 1) (!j - i - 1) :: !r; 11 + j := i 12 + end 13 + done; 14 + String.sub s 0 !j :: !r 15 + 16 + let serve_ssl alpn_protocols port callback = 17 + 18 + let tag = "server" in 19 + 20 + X509_lwt.private_of_pems 21 + ~cert:server_cert 22 + ~priv_key:server_key >>= fun certificate -> 23 + 24 + let server_s = 25 + let open Lwt_unix in 26 + let s = socket PF_INET SOCK_STREAM 0 in 27 + bind s (ADDR_INET (Unix.inet_addr_any, port)) >|= fun () -> 28 + listen s 10 ; 29 + s in 30 + 31 + let handle ep channels addr = 32 + let alpn = match ep with 33 + | Ok data -> (match data.Tls.Core.alpn_protocol with 34 + | Some a -> a 35 + | None -> "no alpn") 36 + | Error () -> "no session" 37 + in 38 + async @@ fun () -> 39 + Lwt.catch (fun () -> callback alpn channels addr >>= fun () -> yap ~tag "<- handler done") 40 + (function 41 + | Tls_lwt.Tls_alert a -> 42 + yap ~tag @@ "handler: " ^ Tls.Packet.alert_type_to_string a 43 + | exn -> yap ~tag "handler: exception" >>= fun () -> fail exn) 44 + in 45 + 46 + let ps = string_of_int port in 47 + yap ~tag ("-> start @ " ^ ps ^ " (use `openssl s_client -connect host:" ^ ps ^ " -alpn <proto>`), available protocols: " ^ String.concat "," alpn_protocols) >>= fun () -> 48 + let rec loop () = 49 + let config = get_ok (Tls.Config.server ~certificates:(`Single certificate) ~alpn_protocols ()) in 50 + server_s >>= fun s -> 51 + Tls_lwt.Unix.accept config s >>= fun (t, addr) -> 52 + yap ~tag "-> connect" >>= fun () -> 53 + ( handle (Tls_lwt.Unix.epoch t) (Tls_lwt.of_t t) addr ; loop () ) 54 + in 55 + loop () 56 + 57 + 58 + let echo_server protocols port = 59 + serve_ssl protocols port @@ fun alpn (ic, oc) _addr -> 60 + lines ic |> Lwt_stream.iter_s (fun line -> 61 + yap ~tag:("handler alpn: " ^ alpn) ("+ " ^ line) >>= fun () -> 62 + Lwt_io.write_line oc line) 63 + 64 + let () = 65 + let protocols = 66 + try split_on_char ',' Sys.argv.(1) with _ -> [ "h2" ; "http/1.1" ] 67 + in 68 + Lwt_main.run (echo_server protocols 4433)
+61
vendor/opam/tls/lwt/examples/echo_server_sni.ml
··· 1 + 2 + open Lwt 3 + open Ex_common 4 + 5 + let serve_ssl port callback = 6 + 7 + let tag = "server" in 8 + 9 + X509_lwt.private_of_pems 10 + ~cert:(ca_cert_dir ^ "/bar.pem") 11 + ~priv_key:server_key >>= fun barcert -> 12 + 13 + X509_lwt.private_of_pems 14 + ~cert:(ca_cert_dir ^ "/foo.pem") 15 + ~priv_key:server_key >>= fun foocert -> 16 + 17 + let server_s = 18 + let open Lwt_unix in 19 + let s = socket PF_INET SOCK_STREAM 0 in 20 + bind s (ADDR_INET (Unix.inet_addr_any, port)) >|= fun () -> 21 + listen s 10 ; 22 + s in 23 + 24 + let handle ep channels addr = 25 + let host = match ep with 26 + | Ok data -> ( match data.Tls.Core.own_name with 27 + | Some n -> Domain_name.to_string n 28 + | None -> "no name" ) 29 + | Error () -> "no session" 30 + in 31 + async @@ fun () -> 32 + Lwt.catch (fun () -> callback host channels addr >>= fun () -> yap ~tag "<- handler done") 33 + (function 34 + | Tls_lwt.Tls_alert a -> 35 + yap ~tag @@ "handler: " ^ Tls.Packet.alert_type_to_string a 36 + | exn -> yap ~tag "handler: exception" >>= fun () -> fail exn) 37 + in 38 + 39 + let ps = string_of_int port in 40 + yap ~tag ("-> start @ " ^ ps ^ " (use `openssl s_client -connect host:" ^ ps ^ " -servername foo` (or -servername bar))") >>= fun () -> 41 + let rec loop () = 42 + let config = get_ok (Tls.Config.server ~certificates:(`Multiple [barcert ; foocert]) ()) in 43 + server_s >>= fun s -> 44 + Tls_lwt.Unix.accept config s >>= fun (t, addr) -> 45 + yap ~tag "-> connect" >>= fun () -> 46 + ( handle (Tls_lwt.Unix.epoch t) (Tls_lwt.of_t t) addr ; loop () ) 47 + in 48 + loop () 49 + 50 + 51 + let echo_server port = 52 + serve_ssl port @@ fun host (ic, oc) _addr -> 53 + lines ic |> Lwt_stream.iter_s (fun line -> 54 + yap ~tag:("handler " ^ host) ("+ " ^ line) >>= fun () -> 55 + Lwt_io.write_line oc line) 56 + 57 + let () = 58 + let port = 59 + try int_of_string Sys.argv.(1) with _ -> 4433 60 + in 61 + Lwt_main.run (echo_server port)
+55
vendor/opam/tls/lwt/examples/ex_common.ml
··· 1 + 2 + open Lwt 3 + 4 + let o f g x = f (g x) 5 + 6 + let ca_cert_dir = "./certificates" 7 + let server_cert = "./certificates/server.pem" 8 + let server_key = "./certificates/server.key" 9 + let server_ec_cert = "./certificates/server-ec.pem" 10 + let server_ec_key = "./certificates/server-ec.key" 11 + 12 + let yap ~tag msg = Lwt_io.printf "(%s %s)\n%!" tag msg 13 + 14 + let lines ic = 15 + Lwt_stream.from @@ fun () -> 16 + Lwt_io.read_line_opt ic >>= function 17 + | None -> Lwt_io.close ic >>= fun () -> return_none 18 + | line -> return line 19 + 20 + let print_alert where alert = 21 + Printf.eprintf "(TLS ALERT (%s): %s)\n%!" 22 + where (Tls.Packet.alert_type_to_string alert) 23 + 24 + let print_fail where fail = 25 + Printf.eprintf "(TLS FAIL (%s): %s)\n%!" 26 + where (Tls.Engine.string_of_failure fail) 27 + 28 + let null_auth ?ip:_ ~host:_ _ = Ok None 29 + 30 + let auth ?ca ?fp () = 31 + match ca with 32 + | Some "NONE" when fp = None -> Lwt.return null_auth 33 + | _ -> 34 + let a = match ca, fp with 35 + | None, Some fp -> `Hex_key_fingerprint (`SHA256, fp) 36 + | None, _ -> `Ca_dir ca_cert_dir 37 + | Some f, _ -> `Ca_file f 38 + in 39 + X509_lwt.authenticator a 40 + 41 + let setup_log style_renderer level = 42 + Fmt_tty.setup_std_outputs ?style_renderer (); 43 + Logs.set_level level; 44 + Logs.set_reporter (Logs_fmt.reporter ~dst:Format.std_formatter ()) 45 + 46 + open Cmdliner 47 + 48 + let setup_log = 49 + Term.(const setup_log 50 + $ Fmt_cli.style_renderer () 51 + $ Logs_cli.level ()) 52 + 53 + let get_ok = function 54 + | Ok cfg -> cfg 55 + | Error `Msg msg -> invalid_arg msg
+101
vendor/opam/tls/lwt/examples/fuzz_server.ml
··· 1 + open Lwt 2 + open Ex_common 3 + 4 + let string_of_unix_err err f p = 5 + Printf.sprintf "Unix_error (%s, %s, %s)" 6 + (Unix.error_message err) f p 7 + 8 + let add_to_cache, find_in_cache = 9 + let c = ref [] in 10 + (fun ticket session -> 11 + let id = ticket.Tls.Core.identifier in 12 + Logs.info (fun m -> m "adding id %a to cache" Ohex.pp id) ; 13 + c := (id, (ticket, session)) :: !c), 14 + (fun id -> match List.find_opt (fun (id', _) -> String.compare id id' = 0) !c with 15 + | None -> None 16 + | Some (_, ep) -> Some ep) 17 + 18 + let ticket_cache = { 19 + Tls.Config.lookup = find_in_cache ; 20 + ticket_granted = add_to_cache ; 21 + lifetime = 300l ; 22 + timestamp = Ptime_clock.now 23 + } 24 + 25 + let serve_ssl port callback = 26 + 27 + let tag = "server" in 28 + 29 + X509_lwt.private_of_pems 30 + ~cert:server_cert 31 + ~priv_key:server_key >>= fun cert -> 32 + 33 + let server_s () = 34 + let open Lwt_unix in 35 + let s = socket PF_INET SOCK_STREAM 0 in 36 + setsockopt s SO_REUSEADDR true ; 37 + bind s (ADDR_INET (Unix.inet_addr_any, port)) >|= fun () -> 38 + listen s 10 ; 39 + s in 40 + 41 + let handle channels addr = 42 + async @@ fun () -> 43 + Lwt.catch (fun () -> callback channels addr >>= fun () -> yap ~tag "<- handler done") 44 + (function 45 + | Tls_lwt.Tls_alert a -> 46 + yap ~tag @@ "handler: " ^ Tls.Packet.alert_type_to_string a 47 + | Tls_lwt.Tls_failure a -> 48 + yap ~tag @@ "handler: " ^ Tls.Engine.string_of_failure a 49 + | Unix.Unix_error (e, f, p) -> 50 + yap ~tag @@ "handler: " ^ (string_of_unix_err e f p) 51 + | _exn -> yap ~tag "handler: exception") 52 + in 53 + 54 + yap ~tag ("-> start @ " ^ string_of_int port) >>= fun () -> 55 + let rec loop s = 56 + let config = get_ok (Tls.Config.server ~ticket_cache ~reneg:true ~certificates:(`Single cert) ~version:(`TLS_1_2, `TLS_1_3) ~zero_rtt:32768l ()) in 57 + (Lwt.catch 58 + (fun () -> Tls_lwt.Unix.accept config s >|= fun r -> `R r) 59 + (function 60 + | Unix.Unix_error (e, f, p) -> return (`L (string_of_unix_err e f p)) 61 + | Tls_lwt.Tls_alert a -> return (`L (Tls.Packet.alert_type_to_string a)) 62 + | Tls_lwt.Tls_failure f -> return (`L (Tls.Engine.string_of_failure f)) 63 + | exn -> let str = Printexc.to_string exn in return (`L ("loop: exception " ^ str)))) >>= function 64 + | `R (t, addr) -> 65 + let channels = Tls_lwt.of_t t in 66 + yap ~tag "-> connect" >>= fun () -> ( handle channels addr ; loop s ) 67 + | `L (msg) -> 68 + yap ~tag ("server socket: " ^ msg) >>= fun () -> loop s 69 + in 70 + server_s () >>= fun s -> 71 + loop s 72 + 73 + let echo_server port = 74 + serve_ssl port @@ fun (ic, oc) _addr -> 75 + yap ~tag:"handler" "accepted" >>= fun () -> 76 + let out = "HTTP/1.1 404 Not Found\r\n\r\n" in 77 + Lwt_io.write_from_string_exactly oc out 0 (String.length out) >>= fun () -> 78 + (* Lwt_io.close oc *) 79 + let rec loop () = 80 + Lwt_io.read_line ic >>= fun line -> 81 + yap ~tag:"handler" ("+ " ^ line) >>= fun () -> 82 + loop () 83 + in 84 + loop () 85 + 86 + let jump _ port = 87 + Lwt_main.run (echo_server port) 88 + 89 + open Cmdliner 90 + 91 + let port = 92 + let doc = "Port to connect to" in 93 + Arg.(value & opt int 4433 & info [ "port" ] ~doc) 94 + 95 + let cmd = 96 + let term = Term.(ret (const jump $ setup_log $ port)) 97 + and info = Cmd.info "fuzz_server" ~version:"%%VERSION_NUM%%" 98 + in 99 + Cmd.v info term 100 + 101 + let () = exit (Cmd.eval cmd)
+29
vendor/opam/tls/lwt/examples/http_client.ml
··· 1 + 2 + open Lwt 3 + open Ex_common 4 + 5 + let http_client ?ca ?fp hostname port = 6 + let port = int_of_string port in 7 + auth ?ca ?fp () >>= fun authenticator -> 8 + Tls_lwt.connect_ext 9 + (get_ok (Tls.Config.client ~authenticator ())) 10 + (hostname, port) >>= fun (ic, oc) -> 11 + let req = String.concat "\r\n" [ 12 + "GET / HTTP/1.1" ; "Host: " ^ hostname ; "Connection: close" ; "" ; "" 13 + ] in 14 + Lwt_io.(write oc req >>= fun () -> read ic >>= print >>= fun () -> printf "++ done.\n%!") 15 + 16 + let () = 17 + try 18 + match Sys.argv with 19 + | [| _ ; host ; port ; "FP" ; fp |] -> Lwt_main.run (http_client host port ~fp) 20 + | [| _ ; host ; port ; trust |] -> Lwt_main.run (http_client host port ~ca:trust) 21 + | [| _ ; host ; port |] -> Lwt_main.run (http_client host port) 22 + | [| _ ; host |] -> Lwt_main.run (http_client host "443") 23 + | args -> Printf.eprintf "%s <host> <port>\n%!" args.(0) 24 + with 25 + | Tls_lwt.Tls_alert alert as exn -> 26 + print_alert "remote end" alert ; raise exn 27 + | Tls_lwt.Tls_failure fail as exn -> 28 + print_fail "our end" fail ; raise exn 29 +
+39
vendor/opam/tls/lwt/examples/resume_client.ml
··· 1 + 2 + open Lwt 3 + open Ex_common 4 + 5 + let http_client ?ca ?fp hostname port = 6 + let port = int_of_string port in 7 + auth ?ca ?fp () >>= fun authenticator -> 8 + let config = get_ok (Tls.Config.client ~authenticator ()) in 9 + Tls_lwt.Unix.connect config (hostname, port) >>= fun t -> 10 + Tls_lwt.Unix.write t "foo\n" >>= fun () -> 11 + let cs = Bytes.create 4 in 12 + Tls_lwt.Unix.read t cs >>= fun _len -> 13 + let cached_session = match Tls_lwt.Unix.epoch t with 14 + | Ok e -> e 15 + | Error () -> invalid_arg "error retrieving epoch" 16 + in 17 + Tls_lwt.Unix.close t >>= fun () -> 18 + Printf.printf "closed session\n" ; 19 + let config = get_ok (Tls.Config.client ~authenticator ~cached_session ()) in 20 + Tls_lwt.connect_ext config (hostname, port) >>= fun (ic, oc) -> 21 + let req = String.concat "\r\n" [ 22 + "GET / HTTP/1.1" ; "Host: " ^ hostname ; "Connection: close" ; "" ; "" 23 + ] in 24 + Lwt_io.(write oc req >>= fun () -> read ic >>= print >>= fun () -> printf "++ done.\n%!") 25 + 26 + let () = 27 + try 28 + match Sys.argv with 29 + | [| _ ; host ; port ; "FP" ; fp |] -> Lwt_main.run (http_client host port ~fp) 30 + | [| _ ; host ; port ; trust |] -> Lwt_main.run (http_client host port ~ca:trust) 31 + | [| _ ; host ; port |] -> Lwt_main.run (http_client host port) 32 + | [| _ ; host |] -> Lwt_main.run (http_client host "443") 33 + | args -> Printf.eprintf "%s <host> <port>\n%!" args.(0) 34 + with 35 + | Tls_lwt.Tls_alert alert as exn -> 36 + print_alert "remote end" alert ; raise exn 37 + | Tls_lwt.Tls_failure fail as exn -> 38 + print_fail "our end" fail ; raise exn 39 +
+123
vendor/opam/tls/lwt/examples/resume_echo_server.ml
··· 1 + open Lwt 2 + open Ex_common 3 + 4 + let string_of_unix_err err f p = 5 + Printf.sprintf "Unix_error (%s, %s, %s)" 6 + (Unix.error_message err) f p 7 + 8 + 9 + module HT = Hashtbl.Make (Tls.Core.PreSharedKeyID) 10 + let cache_psk, psk_cache = 11 + let cache = HT.create 7 in 12 + ((fun psk ed -> HT.add cache psk.Tls.Core.identifier (psk, ed)), 13 + HT.find_opt cache) 14 + 15 + let ticket_cache = { 16 + Tls.Config.lookup = psk_cache ; 17 + ticket_granted = cache_psk ; 18 + lifetime = 300l ; 19 + timestamp = Ptime_clock.now 20 + } 21 + 22 + let serve_ssl port callback = 23 + 24 + let tag = "server" in 25 + 26 + X509_lwt.private_of_pems 27 + ~cert:server_cert 28 + ~priv_key:server_key >>= fun cert -> 29 + 30 + let hex = Ohex.decode in 31 + let epoch = 32 + { 33 + Tls.Core.side = `Client ; 34 + state = `Established ; 35 + protocol_version = `TLS_1_3 ; 36 + ciphersuite = `DHE_RSA_WITH_AES_128_GCM_SHA256 ; 37 + peer_random = hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; 38 + peer_certificate_chain = [] ; 39 + peer_certificate = None ; 40 + peer_name = None ; 41 + trust_anchor = None ; 42 + received_certificates = [] ; 43 + own_random = hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; 44 + own_certificate = fst cert ; 45 + own_private_key = Some (snd cert) ; 46 + own_name = Some Domain_name.(host_exn (of_string_exn "tls13test.nqsb.io")) ; 47 + master_secret = hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; 48 + exporter_master_secret = "" ; 49 + session_id = "" ; 50 + extended_ms = true ; 51 + alpn_protocol = None ; 52 + tls_unique = None ; 53 + } 54 + and psk = { 55 + Tls.Core.identifier = hex "0000" ; 56 + obfuscation = Randomconv.int32 Mirage_crypto_rng.generate ; 57 + secret = hex "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" ; 58 + lifetime = 300l ; 59 + early_data = 0l ; 60 + issued_at = Ptime_clock.now (); 61 + } 62 + in 63 + cache_psk psk epoch ; 64 + 65 + let server_s () = 66 + let open Lwt_unix in 67 + let s = socket PF_INET SOCK_STREAM 0 in 68 + setsockopt s SO_REUSEADDR true ; 69 + bind s (ADDR_INET (Unix.inet_addr_any, port)) >|= fun () -> 70 + listen s 10 ; 71 + s in 72 + 73 + let handle channels = 74 + async @@ fun () -> 75 + Lwt.catch (fun () -> callback channels >>= fun () -> yap ~tag "<- handler done") 76 + (function 77 + | Tls_lwt.Tls_alert a -> 78 + yap ~tag @@ "handler: " ^ Tls.Packet.alert_type_to_string a 79 + | Tls_lwt.Tls_failure a -> 80 + yap ~tag @@ "handler: " ^ Tls.Engine.string_of_failure a 81 + | Unix.Unix_error (e, f, p) -> 82 + yap ~tag @@ "handler: " ^ (string_of_unix_err e f p) 83 + | _exn -> yap ~tag "handler: exception") 84 + in 85 + 86 + yap ~tag ("-> start @ " ^ string_of_int port) >>= fun () -> 87 + let rec loop s = 88 + let authenticator ?ip:_ ~host:_ _ = Ok None in 89 + let config = get_ok (Tls.Config.server ~certificates:(`Single cert) ~ticket_cache ~authenticator ()) in 90 + (Lwt.catch 91 + (fun () -> 92 + Lwt_unix.accept s >>= fun (s, addr) -> 93 + let txt = Unix.(match addr with 94 + | ADDR_UNIX x -> "unix-" ^ x 95 + | ADDR_INET (ip, p) -> string_of_inet_addr ip ^ ":" ^ string_of_int p) 96 + in 97 + yap ~tag:"client-connect" txt >>= fun () -> 98 + Tls_lwt.Unix.server_of_fd config s >|= fun t -> `R t) 99 + (function 100 + | Unix.Unix_error (e, f, p) -> return (`L (string_of_unix_err e f p)) 101 + | Tls_lwt.Tls_alert a -> return (`L (Tls.Packet.alert_type_to_string a)) 102 + | Tls_lwt.Tls_failure f -> return (`L (Tls.Engine.string_of_failure f)) 103 + | exn -> let str = Printexc.to_string exn in return (`L ("loop: exception " ^ str)))) >>= function 104 + | `R t -> 105 + yap ~tag "-> connect" >>= fun () -> 106 + handle (Tls_lwt.of_t t); loop s 107 + | `L msg -> 108 + yap ~tag ("server socket: " ^ msg) >>= fun () -> loop s 109 + in 110 + server_s () >>= fun s -> 111 + loop s 112 + 113 + let echo_server port = 114 + serve_ssl port @@ fun (ic, oc) -> 115 + lines ic |> Lwt_stream.iter_s (fun line -> 116 + yap ~tag:"handler" ("+ " ^ string_of_int (String.length line)) >>= fun () -> 117 + Lwt_io.write_line oc line) 118 + 119 + let () = 120 + let port = 121 + try int_of_string Sys.argv.(1) with _ -> 4433 122 + in 123 + Lwt_main.run (echo_server port)
+74
vendor/opam/tls/lwt/examples/starttls_server.ml
··· 1 + open Lwt.Infix 2 + open Ex_common 3 + 4 + let capability = "[CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN] server ready.\r\n" 5 + 6 + let ok_starttls = "OK STARTTLS\r\n" 7 + 8 + let cert () = 9 + X509_lwt.private_of_pems 10 + ~cert:"./certificates/server.pem" 11 + ~priv_key:"./certificates/server.key" 12 + 13 + let init_socket addr port = 14 + let sockaddr = Unix.ADDR_INET (Unix.inet_addr_of_string addr, port) in 15 + let socket = Lwt_unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in 16 + Lwt_unix.setsockopt socket Unix.SO_REUSEADDR true; 17 + Lwt_unix.bind socket sockaddr >|= fun () -> 18 + socket 19 + 20 + let create_srv_socket addr port = 21 + init_socket addr port >|= fun socket -> 22 + Lwt_unix.listen socket 10; 23 + socket 24 + 25 + let accept sock = 26 + Lwt_unix.accept sock >>= fun (sock_cl, addr) -> 27 + let ic = Lwt_io.of_fd ~close:(fun () -> Lwt.return_unit) ~mode:Lwt_io.input sock_cl in 28 + let oc = Lwt_io.of_fd ~close:(fun () -> Lwt.return_unit) ~mode:Lwt_io.output sock_cl in 29 + Lwt.return ((ic,oc), addr, sock_cl) 30 + 31 + let start_server () = 32 + let write oc buff = 33 + Lwt_io.write oc buff >>= fun () -> Lwt_io.flush oc 34 + in 35 + let read ic = 36 + Lwt_io.read ic ~count:2048 >>= fun buff -> 37 + Printf.printf "%s%!" buff; 38 + Lwt.return buff 39 + in 40 + let parse buff = 41 + match String.index buff ' ' with 42 + | exception Not_found -> "", "" 43 + | idx -> 44 + let l = String.length buff in 45 + String.sub buff 0 idx, String.sub buff (succ idx) (l - succ idx) 46 + in 47 + let rec wait_cmd sock_cl ic oc = 48 + read ic >>= fun buff -> 49 + let tag,cmd = parse buff in 50 + match cmd with 51 + | "CAPABILITY" -> 52 + write oc ("* " ^ capability ^ tag ^ " OK CAPABILITY\r\n") >>= fun () -> 53 + wait_cmd sock_cl ic oc 54 + | "STARTTLS" -> 55 + write oc (tag ^ ok_starttls) >>= fun () -> 56 + Lwt_io.close ic >>= fun () -> 57 + Lwt_io.close oc >>= fun () -> 58 + cert () >>= fun cert -> 59 + Tls_lwt.Unix.server_of_fd 60 + (get_ok (Tls.Config.server ~certificates:(`Single cert) ())) sock_cl >>= fun s -> 61 + let ic,oc = Tls_lwt.of_t s in 62 + write oc ("* OK " ^ capability) >>= fun () -> 63 + wait_cmd sock_cl ic oc 64 + | _ -> 65 + write oc ("BAD\r\n") >>= fun () -> 66 + wait_cmd sock_cl ic oc 67 + in 68 + create_srv_socket "127.0.0.1" 143 >>= fun sock -> 69 + accept sock >>= fun ((ic,oc), _addr, sock_cl) -> 70 + write oc ("* OK " ^ capability) >>= fun () -> 71 + wait_cmd sock_cl ic oc 72 + 73 + let () = 74 + Lwt_main.run (start_server ())
+49
vendor/opam/tls/lwt/examples/test_client.ml
··· 1 + open Lwt 2 + open Ex_common 3 + 4 + let mypsk = ref None 5 + 6 + let ticket_cache = { 7 + Tls.Config.lookup = (fun _ -> None) ; 8 + ticket_granted = (fun psk epoch -> mypsk := Some (psk, epoch)) ; 9 + lifetime = 0l ; 10 + timestamp = Ptime_clock.now 11 + } 12 + 13 + let test_client _ = 14 + (* X509_lwt.private_of_pems 15 + ~cert:server_cert 16 + ~priv_key:server_key >>= fun cert -> *) 17 + let port = 4433 in 18 + let host = "127.0.0.1" in 19 + let authenticator = null_auth in 20 + Tls_lwt.Unix.connect 21 + (get_ok Tls.Config.(client ~version:(`TLS_1_0, `TLS_1_3) (* ~certificates:(`Single cert) *) ?cached_ticket:!mypsk ~ticket_cache ~authenticator ~ciphers:Ciphers.supported ())) 22 + (host, port) >>= fun t -> 23 + let (ic, oc) = Tls_lwt.of_t t in 24 + let req = String.concat "\r\n" [ 25 + "GET / HTTP/1.1" ; "Host: " ^ host ; "Connection: close" ; "" ; "" 26 + ] in 27 + Lwt_io.(write oc req >>= fun () -> 28 + read ~count:3 ic >>= print >>= fun () -> 29 + close oc >>= fun () -> 30 + printf "++ done.\n%!") 31 + 32 + let jump _ = 33 + try 34 + Lwt_main.run (test_client ()) ; `Ok () 35 + with 36 + | Tls_lwt.Tls_alert alert as exn -> 37 + print_alert "remote end" alert ; raise exn 38 + | Tls_lwt.Tls_failure alert as exn -> 39 + print_fail "our end" alert ; raise exn 40 + 41 + open Cmdliner 42 + 43 + let cmd = 44 + let term = Term.(ret (const jump $ setup_log)) 45 + and info = Cmd.info "test_client" ~version:"%%VERSION_NUM%%" 46 + in 47 + Cmd.v info term 48 + 49 + let () = exit (Cmd.eval cmd)
+47
vendor/opam/tls/lwt/examples/test_server.ml
··· 1 + 2 + open Lwt 3 + open Ex_common 4 + 5 + let serve_ssl port callback = 6 + 7 + let tag = "server" in 8 + 9 + X509_lwt.private_of_pems 10 + ~cert:server_cert 11 + ~priv_key:server_key >>= fun certificate -> 12 + X509_lwt.private_of_pems 13 + ~cert:server_ec_cert 14 + ~priv_key:server_ec_key >>= fun ec_certificate -> 15 + let certificates = `Multiple [ certificate ; ec_certificate ] in 16 + let config = 17 + get_ok (Tls.Config.(server ~version:(`TLS_1_0, `TLS_1_3) ~certificates ~ciphers:Ciphers.supported ())) 18 + in 19 + 20 + let server_s = 21 + let open Lwt_unix in 22 + let s = socket PF_INET SOCK_STREAM 0 in 23 + setsockopt s Unix.SO_REUSEADDR true ; 24 + bind s (ADDR_INET (Unix.inet_addr_any, port)) >|= fun () -> 25 + listen s 10 ; 26 + s in 27 + 28 + yap ~tag ("-> start @ " ^ string_of_int port) >>= fun () -> 29 + server_s >>= fun s -> 30 + Tls_lwt.Unix.accept config s >>= fun (t, addr) -> 31 + let channels = Tls_lwt.of_t t in 32 + yap ~tag "-> connect" >>= fun () -> 33 + callback channels addr >>= fun () -> 34 + yap ~tag "<- handler done" 35 + 36 + let test_server port = 37 + serve_ssl port @@ fun (ic, oc) _addr -> 38 + yap ~tag:"handler" "accepted" >>= fun () -> 39 + Lwt_io.read_line ic >>= fun line -> 40 + yap ~tag:"handler" ("+ " ^ line) >>= fun () -> 41 + Lwt_io.write_line oc line 42 + 43 + let () = 44 + let port = 45 + try int_of_string Sys.argv.(1) with _ -> 4433 46 + in 47 + Lwt_main.run (test_server port)
+70
vendor/opam/tls/lwt/examples/tls_over_tls.ml
··· 1 + open Lwt 2 + open Ex_common 3 + 4 + let hostname = "mirage.io" 5 + 6 + let proxy = "127.0.0.1", 3129 7 + 8 + (* To test TLS-over-TLS, the `squid` proxy can be installed locally and configured to support HTTPS: 9 + 10 + - Generate a certificate for localhost: https://gist.github.com/cecilemuller/9492b848eb8fe46d462abeb26656c4f8 11 + 12 + $ openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=US/CN=Example-Root-CA" 13 + $ openssl x509 -outform pem -in RootCA.pem -out RootCA.crt 14 + $ cat <<EOF > domains.ext 15 + authorityKeyIdentifier=keyid,issuer 16 + basicConstraints=CA:FALSE 17 + keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment 18 + subjectAltName = @alt_names 19 + [alt_names] 20 + DNS.1 = localhost 21 + EOF 22 + $ openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost.local" 23 + $ openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt 24 + 25 + - Configure squid by adding HTTPS support on port 3129 in /etc/squid/squid.conf : 26 + 27 + https_port 3129 tls-cert=/path/to/localhost.crt tls-key=/path/to/localhost.key 28 + 29 + *) 30 + 31 + let client = get_ok (Tls.Config.client ~authenticator:null_auth ()) 32 + 33 + let string_prefix ~prefix msg = 34 + let len = String.length prefix in 35 + String.length msg >= len && String.sub msg 0 len = prefix 36 + 37 + let host = Result.get_ok (Domain_name.of_string hostname) 38 + let host = Result.get_ok (Domain_name.host host) 39 + 40 + let test_client _ = 41 + (* Connect to proxy *) 42 + Tls_lwt.Unix.connect client proxy >>= fun t -> 43 + let (ic, oc) = Tls_lwt.of_t t in 44 + 45 + (* Request proxy to connect to hostname *) 46 + let req = 47 + Printf.sprintf "CONNECT %s:443 HTTP/1.1\r\nHost: %s\r\n\r\n" 48 + hostname hostname 49 + in 50 + Lwt_io.write oc req >>= fun () -> 51 + Lwt_io.read ic ~count:1024 >>= fun msg -> 52 + assert (string_prefix ~prefix:"HTTP/1.1 200 " msg) ; 53 + 54 + (* TLS with hostname, over the TLS connection with the proxy *) 55 + Tls_lwt.Unix.client_of_channels client ~host (ic, oc) >>= fun t -> 56 + let (ic, oc) = Tls_lwt.of_t t in 57 + 58 + (* Request homepage from host *) 59 + let req = 60 + Printf.sprintf "GET / HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n" 61 + hostname 62 + in 63 + 64 + Lwt_io.(write oc req >>= fun () -> 65 + read ~count:1024 ic >>= print >>= fun () -> 66 + read ~count:1024 ic >>= print >>= fun () -> 67 + close oc >>= fun () -> 68 + printf "++ done.\n%!") 69 + 70 + let () = Lwt_main.run (test_client ())
+364
vendor/opam/tls/lwt/tls_lwt.ml
··· 1 + open Lwt.Infix 2 + 3 + exception Tls_alert of Tls.Packet.alert_type 4 + exception Tls_failure of Tls.Engine.failure 5 + 6 + (* This really belongs just about anywhere else: generic unix name resolution. *) 7 + let resolve host service = 8 + let open Lwt_unix in 9 + getprotobyname "tcp" >>= fun tcp -> 10 + getaddrinfo host service [AI_PROTOCOL tcp.p_proto] >>= function 11 + | [] -> 12 + let msg = Printf.sprintf "no address for %s:%s" host service in 13 + Lwt.reraise (Invalid_argument msg) 14 + | ai::_ -> Lwt.return ai.ai_addr 15 + 16 + module Lwt_cs = struct 17 + 18 + let naked ~name f fd cs off len = 19 + f fd cs off len >>= fun res -> 20 + match Lwt_unix.getsockopt_error fd with 21 + | None -> Lwt.return res 22 + | Some err -> Lwt.reraise @@ Unix.Unix_error (err, name, "") 23 + 24 + let write = naked ~name:"Tls_lwt.write" Lwt_unix.write 25 + and read = naked ~name:"Tls_lwt.read" Lwt_unix.read 26 + 27 + let rec write_full ?(off = 0) ?len fd buf = 28 + let len = Option.value ~default:(String.length buf - off) len in 29 + if len = 0 then 30 + Lwt.return_unit 31 + else 32 + write fd (Bytes.unsafe_of_string buf) off len >>= fun written -> 33 + write_full ~off:(off + written) ~len:(len - written) fd buf 34 + 35 + let read fd buf = read fd buf 0 (Bytes.length buf) 36 + end 37 + 38 + module Lwt_fd = struct 39 + type t = { 40 + read : bytes -> int Lwt.t ; 41 + write : string -> unit Lwt.t ; 42 + close : unit -> unit Lwt.t ; 43 + } 44 + 45 + let read t cs = t.read cs 46 + let write t cs = t.write cs 47 + let close t = t.close () 48 + 49 + let of_fd fd = 50 + let close () = 51 + (* (partially) avoid double-closes by checking if the fd has already been closed *) 52 + match Lwt_unix.state fd with 53 + | Lwt_unix.Closed -> Lwt.return_unit 54 + | Lwt_unix.Opened | Lwt_unix.Aborted _ -> Lwt_unix.close fd 55 + in 56 + { 57 + read = Lwt_cs.read fd ; 58 + write = Lwt_cs.write_full fd ; 59 + close = close ; 60 + } 61 + 62 + let of_channels ic oc = 63 + { 64 + read = (fun bs -> Lwt_io.read_into ic bs 0 (Bytes.length bs)) ; 65 + write = (Lwt_io.write oc) ; 66 + close = (fun () -> Lwt_io.close oc <&> Lwt_io.close ic) ; 67 + } 68 + end 69 + 70 + module Unix = struct 71 + 72 + type t = { 73 + fd : Lwt_fd.t ; 74 + mutable state : [ `Active of Tls.Engine.state 75 + | `Read_closed of Tls.Engine.state 76 + | `Write_closed of Tls.Engine.state 77 + | `Closed 78 + | `Error of exn ] ; 79 + mutable linger : string option ; 80 + recv_buf : bytes ; 81 + } 82 + 83 + let half_close state mode = 84 + match state, mode with 85 + | `Active tls, `read -> `Read_closed tls 86 + | `Active tls, `write -> `Write_closed tls 87 + | `Active _, `read_write -> `Closed 88 + | `Read_closed tls, `read -> `Read_closed tls 89 + | `Read_closed _, (`write | `read_write) -> `Closed 90 + | `Write_closed tls, `write -> `Write_closed tls 91 + | `Write_closed _, (`read | `read_write) -> `Closed 92 + | (`Closed | `Error _) as e, (`read | `write | `read_write) -> e 93 + 94 + let inject_state tls = function 95 + | `Active _ -> `Active tls 96 + | `Read_closed _ -> `Read_closed tls 97 + | `Write_closed _ -> `Write_closed tls 98 + | (`Closed | `Error _) as e -> e 99 + 100 + let safely th = 101 + Lwt.catch 102 + (fun () -> th >>= fun _ -> Lwt.return_unit) 103 + (function 104 + | Out_of_memory -> raise Out_of_memory 105 + | _ -> Lwt.return_unit) 106 + 107 + let (read_t, write_t) = 108 + let recording_errors op t cs = 109 + Lwt.catch 110 + (fun () -> op t.fd cs) 111 + (function 112 + | Out_of_memory -> raise Out_of_memory 113 + | exn -> (match t.state with 114 + | `Error _ -> () 115 + | _ -> t.state <- `Error exn) ; 116 + Lwt.reraise exn) 117 + in 118 + (recording_errors Lwt_fd.read, recording_errors Lwt_fd.write) 119 + 120 + let when_some f = function None -> Lwt.return_unit | Some x -> f x 121 + 122 + let rec read_react t = 123 + 124 + let handle tls buf = 125 + match Tls.Engine.handle_tls tls buf with 126 + | Ok (state', eof, `Response resp, `Data data) -> 127 + let state' = inject_state state' t.state in 128 + let state' = Option.(value ~default:state' (map (fun `Eof -> half_close state' `read) eof)) in 129 + t.state <- state' ; 130 + safely (resp |> when_some (write_t t)) >|= fun () -> 131 + `Ok data 132 + 133 + | Error (fail, `Response resp) -> 134 + t.state <- `Error (match fail with 135 + | `Alert a -> Tls_alert a 136 + | f -> Tls_failure f); 137 + write_t t resp >>= fun () -> read_react t 138 + in 139 + 140 + match t.state with 141 + | `Error e -> Lwt.reraise e 142 + | `Closed 143 + | `Read_closed _ -> Lwt.return `Eof 144 + | _ -> 145 + read_t t t.recv_buf >>= function 146 + | 0 -> 147 + t.state <- half_close t.state `read; 148 + Lwt.return `Eof 149 + | n -> 150 + match t.state with 151 + | `Error e -> Lwt.reraise e 152 + | `Active tls | `Read_closed tls | `Write_closed tls -> 153 + handle tls (String.sub (Bytes.unsafe_to_string t.recv_buf) 0 n) 154 + | `Closed -> Lwt.return `Eof 155 + 156 + let rec read t ?(off = 0) buf = 157 + if off < 0 || off >= Bytes.length buf then 158 + invalid_arg "offset must be >= 0 and < Bytes.length buf"; 159 + 160 + let writeout res = 161 + let rlen = String.length res in 162 + let n = min (Bytes.length buf - off) rlen in 163 + Bytes.blit_string res 0 buf off n ; 164 + t.linger <- 165 + (if n < rlen then Some (String.sub res n (rlen - n)) else None) ; 166 + Lwt.return n in 167 + 168 + match t.linger with 169 + | Some res -> writeout res 170 + | None -> 171 + read_react t >>= function 172 + | `Eof -> Lwt.return 0 173 + | `Ok None -> read t ~off buf 174 + | `Ok (Some res) -> writeout res 175 + 176 + let writev t css = 177 + match t.state with 178 + | `Error err -> Lwt.reraise err 179 + | `Write_closed _ | `Closed -> Lwt.reraise @@ Invalid_argument "tls: closed socket" 180 + | `Active tls | `Read_closed tls -> 181 + match Tls.Engine.send_application_data tls css with 182 + | Some (tls, tlsdata) -> 183 + ( t.state <- inject_state tls t.state ; write_t t tlsdata ) 184 + | None -> Lwt.reraise @@ Invalid_argument "tls: write: socket not ready" 185 + 186 + let write t cs = writev t [cs] 187 + 188 + (* 189 + * XXX bad XXX 190 + * This is a point that should particularly be protected from concurrent r/w. 191 + * Doing this before a `t` is returned is safe; redoing it during rekeying is 192 + * not, as the API client already sees the `t` and can mistakenly interleave 193 + * writes while this is in progress. 194 + * *) 195 + let rec drain_handshake t = 196 + let push_linger t mcs = 197 + match (mcs, t.linger) with 198 + | (None, _) -> () 199 + | (scs, None) -> t.linger <- scs 200 + | (Some cs, Some l) -> t.linger <- Some (l ^ cs) 201 + in 202 + match t.state with 203 + | `Active tls when not (Tls.Engine.handshake_in_progress tls) -> 204 + Lwt.return t 205 + | _ -> 206 + read_react t >>= function 207 + | `Eof -> Lwt.reraise End_of_file 208 + | `Ok cs -> push_linger t cs ; drain_handshake t 209 + 210 + let reneg ?authenticator ?acceptable_cas ?cert ?(drop = true) t = 211 + match t.state with 212 + | `Error err -> Lwt.reraise err 213 + | `Closed | `Read_closed _ | `Write_closed _ -> 214 + Lwt.reraise @@ Invalid_argument "tls: closed socket" 215 + | `Active tls -> 216 + match Tls.Engine.reneg ?authenticator ?acceptable_cas ?cert tls with 217 + | None -> Lwt.reraise @@ Invalid_argument "tls: can't renegotiate" 218 + | Some (tls', buf) -> 219 + if drop then t.linger <- None ; 220 + t.state <- inject_state tls' t.state ; 221 + write_t t buf >>= fun () -> 222 + drain_handshake t >>= fun _ -> 223 + Lwt.return_unit 224 + 225 + let key_update ?request t = 226 + match t.state with 227 + | `Error err -> Lwt.reraise err 228 + | `Write_closed _ | `Closed -> Lwt.reraise @@ Invalid_argument "tls: closed socket" 229 + | `Active tls | `Read_closed tls -> 230 + match Tls.Engine.key_update ?request tls with 231 + | Error f -> Lwt.reraise @@ Invalid_argument (Format.asprintf "tls: can't update key: %a" Tls.Engine.pp_failure f) 232 + | Ok (tls', buf) -> 233 + t.state <- inject_state tls' t.state ; 234 + write_t t buf 235 + 236 + let shutdown t mode = 237 + (match mode with 238 + | `read -> Lwt.return_unit 239 + | `write | `read_write -> 240 + match t.state with 241 + | `Active tls | `Read_closed tls -> 242 + let tls', buf = Tls.Engine.send_close_notify tls in 243 + t.state <- inject_state tls' (half_close t.state `write) ; 244 + write_t t buf 245 + | _ -> Lwt.return_unit) >>= fun () -> 246 + t.state <- half_close t.state mode; 247 + match t.state with 248 + | `Closed | `Error _ -> safely (Lwt_fd.close t.fd) 249 + | _ -> Lwt.return_unit 250 + 251 + let close t = shutdown t `read_write 252 + 253 + let server_of_fd config fd = 254 + drain_handshake { 255 + state = `Active (Tls.Engine.server config) ; 256 + fd = fd ; 257 + linger = None ; 258 + recv_buf = Bytes.create 4096 259 + } 260 + 261 + let server_of_channels config (ic, oc) = 262 + server_of_fd config (Lwt_fd.of_channels ic oc) 263 + 264 + let server_of_fd config fd = 265 + server_of_fd config (Lwt_fd.of_fd fd) 266 + 267 + let client_of_fd config ?host fd = 268 + let config' = match host with 269 + | None -> config 270 + | Some host -> Tls.Config.peer config host 271 + in 272 + let (tls, init) = Tls.Engine.client config' in 273 + let t = { 274 + state = `Active tls ; 275 + fd = fd ; 276 + linger = None ; 277 + recv_buf = Bytes.create 4096 278 + } 279 + in 280 + write_t t init >>= fun () -> 281 + drain_handshake t 282 + 283 + let client_of_channels config ?host (ic, oc) = 284 + client_of_fd config ?host (Lwt_fd.of_channels ic oc) 285 + 286 + let client_of_fd config ?host fd = 287 + client_of_fd config ?host (Lwt_fd.of_fd fd) 288 + 289 + let accept conf fd = 290 + Lwt_unix.accept fd >>= fun (fd', addr) -> 291 + Lwt.catch (fun () -> server_of_fd conf fd' >|= fun t -> (t, addr)) 292 + (function 293 + | Out_of_memory -> raise Out_of_memory 294 + | exn -> safely (Lwt_unix.close fd') >>= fun () -> Lwt.reraise exn) 295 + 296 + let connect conf (host, port) = 297 + resolve host (string_of_int port) >>= fun addr -> 298 + let fd = Lwt_unix.(socket (Unix.domain_of_sockaddr addr) SOCK_STREAM 0) in 299 + Lwt.catch (fun () -> 300 + let host = 301 + Result.to_option 302 + (Result.bind (Domain_name.of_string host) Domain_name.host) 303 + in 304 + Lwt_unix.connect fd addr >>= fun () -> client_of_fd conf ?host fd) 305 + (function 306 + | Out_of_memory -> raise Out_of_memory 307 + | exn -> safely (Lwt_unix.close fd) >>= fun () -> Lwt.reraise exn) 308 + 309 + let read_bytes t bs off len = 310 + let buf = Bytes.create len in 311 + read t buf >|= fun n -> 312 + let to_copy = min n len in 313 + Lwt_bytes.blit_from_bytes buf 0 bs off to_copy; 314 + to_copy 315 + 316 + let write_bytes t bs off len = 317 + let buf = Bytes.create len in 318 + Lwt_bytes.blit_to_bytes bs off buf 0 len; 319 + write t (Bytes.unsafe_to_string buf) 320 + 321 + let epoch t = 322 + match t.state with 323 + | `Active tls | `Read_closed tls | `Write_closed tls -> Tls.Engine.epoch tls 324 + | `Closed | `Error _ -> Error () 325 + end 326 + 327 + type ic = Lwt_io.input_channel 328 + type oc = Lwt_io.output_channel 329 + 330 + let of_t ?close t = 331 + let close = match close with 332 + | Some f -> (fun () -> Unix.safely (f ())) 333 + | None -> (fun () -> Unix.(safely (close t))) 334 + in 335 + (Lwt_io.make ~close ~mode:Lwt_io.Input (Unix.read_bytes t)), 336 + (Lwt_io.make ~close ~mode:Lwt_io.Output @@ 337 + fun a b c -> Unix.write_bytes t a b c >>= fun () -> Lwt.return c) 338 + 339 + let accept_ext conf fd = 340 + Unix.accept conf fd >|= fun (t, peer) -> (of_t t, peer) 341 + 342 + and connect_ext conf addr = 343 + Unix.connect conf addr >|= of_t 344 + 345 + let accept certificate fd = 346 + match Tls.Config.server ~certificates:certificate () with 347 + | Ok config -> accept_ext config fd >|= fun w -> Ok w 348 + | Error _ as e -> Lwt.return e 349 + 350 + and connect authenticator addr = 351 + match Tls.Config.client ~authenticator () with 352 + | Ok config -> connect_ext config addr >|= fun w -> Ok w 353 + | Error _ as e -> Lwt.return e 354 + 355 + (* Boot the entropy loop at module init time. *) 356 + let () = Mirage_crypto_rng_unix.use_default () 357 + 358 + let () = 359 + Printexc.register_printer (function 360 + | Tls_alert typ -> 361 + Some ("TLS alert from peer: " ^ Tls.Packet.alert_type_to_string typ) 362 + | Tls_failure f -> 363 + Some ("TLS failure: " ^ Tls.Engine.string_of_failure f) 364 + | _ -> None)
+129
vendor/opam/tls/lwt/tls_lwt.mli
··· 1 + (** Effectful operations using Lwt for pure TLS. 2 + 3 + The pure TLS is state and buffer in, state and buffer out. This 4 + module uses Lwt for communication over the network. 5 + 6 + This module implements a high-level API and a low-level API (in 7 + {!Unix}). Most applications should use the high-level API described below. *) 8 + 9 + (** [Tls_alert] exception received from the other endpoint *) 10 + exception Tls_alert of Tls.Packet.alert_type 11 + 12 + (** [Tls_failure] exception while processing incoming data *) 13 + exception Tls_failure of Tls.Engine.failure 14 + 15 + (** Low-level API *) 16 + module Unix : sig 17 + 18 + (** {1 Unix API} *) 19 + 20 + (** It is the responsibility of the client to handle error 21 + conditions. The underlying file descriptors are not closed. *) 22 + 23 + (** Abstract type of a session *) 24 + type t 25 + 26 + (** {2 Constructors} *) 27 + 28 + (** [server_of_fd server fd] is [t], after server-side TLS 29 + handshake of [fd] using [server] configuration. *) 30 + val server_of_fd : Tls.Config.server -> Lwt_unix.file_descr -> t Lwt.t 31 + 32 + (** [server_of_channels server (ic, oc)] is [t], after server-side TLS 33 + handshake on the input/output channels [ic, oc] using [server] configuration. *) 34 + val server_of_channels : Tls.Config.server -> Lwt_io.input_channel * Lwt_io.output_channel -> t Lwt.t 35 + 36 + (** [client_of_fd client ~host fd] is [t], after client-side 37 + TLS handshake of [fd] using [client] configuration and [host]. *) 38 + val client_of_fd : Tls.Config.client -> ?host:[ `host ] Domain_name.t -> Lwt_unix.file_descr -> t Lwt.t 39 + 40 + (** [client_of_channels client ~host (ic, oc)] is [t], after client-side 41 + TLS handshake over the input/output channels [ic, oc] using [client] configuration and [host]. *) 42 + val client_of_channels : Tls.Config.client -> ?host:[ `host ] Domain_name.t -> Lwt_io.input_channel * Lwt_io.output_channel -> t Lwt.t 43 + 44 + (** [accept server fd] is [t, sockaddr], after accepting a 45 + client on [fd] and upgrading to a TLS connection. *) 46 + val accept : Tls.Config.server -> Lwt_unix.file_descr -> (t * Lwt_unix.sockaddr) Lwt.t 47 + 48 + (** [connect client (host, port)] is [t], after successful 49 + connection to [host] on [port] and TLS upgrade. *) 50 + val connect : Tls.Config.client -> string * int -> t Lwt.t 51 + 52 + (** {2 Common stream operations} *) 53 + 54 + (** [read t ~off buffer] is [length], the number of bytes read into 55 + [buffer]. It fills [buffer] starting at [off] (default is 0). *) 56 + val read : t -> ?off:int -> bytes -> int Lwt.t 57 + 58 + (** [write t buffer] writes the [buffer] to the session. *) 59 + val write : t -> string -> unit Lwt.t 60 + 61 + (** [writev t buffers] writes the [buffers] to the session. *) 62 + val writev : t -> string list -> unit Lwt.t 63 + 64 + (** [read_bytes t bytes offset len] is [read_bytes], the amount of 65 + bytes read. *) 66 + val read_bytes : t -> Lwt_bytes.t -> int -> int -> int Lwt.t 67 + 68 + (** [write_bytes t bytes offset length] writes [length] bytes of 69 + [bytes] starting at [offset] to the session. *) 70 + val write_bytes : t -> Lwt_bytes.t -> int -> int -> unit Lwt.t 71 + 72 + (** [shutdown t direction] closes the [direction] of the TLS session [t]. 73 + If [`read_write] or [`write] is closed, a TLS close_notify is sent to the 74 + other endpoint. If this results in a fully closed session (or an 75 + errorneous session), the underlying file descriptor is closed. *) 76 + val shutdown : t -> [ `read | `write | `read_write ] -> unit Lwt.t 77 + 78 + (** [close t] closes the TLS session and the underlying file descriptor. *) 79 + val close : t -> unit Lwt.t 80 + 81 + (** [reneg ~authenticator ~acceptable_cas ~cert ~drop t] renegotiates the 82 + session, and blocks until the renegotiation finished. Optionally, a new 83 + [authenticator] and [acceptable_cas] can be used. The own certificate can 84 + be adjusted by [cert]. If [drop] is [true] (the default), 85 + application data received before the renegotiation finished is dropped. *) 86 + val reneg : ?authenticator:X509.Authenticator.t -> 87 + ?acceptable_cas:X509.Distinguished_name.t list -> ?cert:Tls.Config.own_cert -> 88 + ?drop:bool -> t -> unit Lwt.t 89 + 90 + (** [key_update ~request t] updates the traffic key and requests a traffic key 91 + update from the peer if [request] is provided and [true] (the default). 92 + This is only supported in TLS 1.3. *) 93 + val key_update : ?request:bool -> t -> unit Lwt.t 94 + 95 + (** [epoch t] returns [epoch], which contains information of the 96 + active session. *) 97 + val epoch : t -> (Tls.Core.epoch_data, unit) result 98 + end 99 + 100 + (** {1 High-level API} *) 101 + 102 + type ic = Lwt_io.input_channel 103 + type oc = Lwt_io.output_channel 104 + 105 + (** [accept_ext server fd] is [(ic, oc), sockaddr], the input 106 + and output channel from an accepted connection on the given [fd], 107 + after upgrading to TLS using the [server] configuration. *) 108 + val accept_ext : Tls.Config.server -> Lwt_unix.file_descr -> 109 + ((ic * oc) * Lwt_unix.sockaddr) Lwt.t 110 + 111 + (** [accept own_cert fd] is [(ic, oc), sockaddr], the input and 112 + output channel from the accepted connection on [fd], using the 113 + default configuration with the given [own_cert]. *) 114 + val accept : Tls.Config.own_cert -> Lwt_unix.file_descr -> 115 + ((ic * oc) * Lwt_unix.sockaddr, [> `Msg of string]) result Lwt.t 116 + 117 + (** [connect_ext client (host, port)] is [ic, oc], the input 118 + and output channel of a TLS connection to [host] on [port] using 119 + the [client] configuration. *) 120 + val connect_ext : Tls.Config.client -> string * int -> (ic * oc) Lwt.t 121 + 122 + (** [connect authenticator (host, port)] is [ic, oc], the input 123 + and output channel of a TLS connection to [host] on [port] using the 124 + default configuration and the [authenticator]. *) 125 + val connect : X509.Authenticator.t -> string * int -> (ic * oc, [> `Msg of string ]) result Lwt.t 126 + 127 + (** [of_t t] is [ic, oc], the input and output channel. [close] 128 + defaults to [!Unix.close]. *) 129 + val of_t : ?close:(unit -> unit Lwt.t) -> Unix.t -> ic * oc
+109
vendor/opam/tls/lwt/x509_lwt.ml
··· 1 + open Lwt 2 + 3 + let failure msg = fail @@ Failure msg 4 + 5 + let catch_invalid_arg th h = 6 + Lwt.catch (fun () -> th) 7 + (function 8 + | Invalid_argument msg -> h msg 9 + | exn -> fail exn) 10 + 11 + let (</>) a b = a ^ "/" ^ b 12 + 13 + let o f g x = f (g x) 14 + 15 + let read_file path = 16 + let open Lwt_io in 17 + open_file ~mode:Input path >>= fun file -> 18 + read file >>= fun cs -> 19 + close file >|= fun () -> 20 + cs 21 + 22 + let read_dir path = 23 + let open Lwt_unix in 24 + let rec collect acc d = 25 + readdir_n d 10 >>= function 26 + | [||] -> return acc 27 + | xs -> collect (Array.to_list xs @ acc) d in 28 + opendir path >>= fun dir -> 29 + collect [] dir >>= fun entries -> 30 + closedir dir >|= fun () -> 31 + entries 32 + 33 + let extension str = 34 + let n = String.length str in 35 + let rec scan = function 36 + | i when i = 0 -> None 37 + | i when str.[i - 1] = '.' -> 38 + Some (String.sub str i (n - i)) 39 + | i -> scan (pred i) in 40 + scan n 41 + 42 + 43 + let private_of_pems ~cert ~priv_key = 44 + catch_invalid_arg 45 + (read_file cert >|= fun pem -> 46 + match X509.Certificate.decode_pem_multiple pem with 47 + | Ok cs -> cs 48 + | Error (`Msg m) -> invalid_arg ("failed to parse certificates " ^ m)) 49 + (o failure @@ Printf.sprintf "Private certificates (%s): %s" cert) >>= fun certs -> 50 + catch_invalid_arg 51 + (read_file priv_key >|= fun pem -> 52 + match X509.Private_key.decode_pem pem with 53 + | Ok key -> key 54 + | Error (`Msg m) -> invalid_arg ("failed to parse private key " ^ m)) 55 + (o failure @@ Printf.sprintf "Private key (%s): %s" priv_key) >>= fun pk -> 56 + return (certs, pk) 57 + 58 + let certs_of_pem path = 59 + catch_invalid_arg 60 + (read_file path >|= fun pem -> 61 + match X509.Certificate.decode_pem_multiple pem with 62 + | Ok cs -> cs 63 + | Error (`Msg m) -> invalid_arg ("failed to parse certificates " ^ m)) 64 + (o failure @@ Printf.sprintf "Certificates in %s: %s" path) 65 + 66 + let certs_of_pem_dir path = 67 + read_dir path 68 + >|= List.filter (fun file -> extension file = Some "crt") 69 + >>= Lwt_list.map_p (fun file -> certs_of_pem (path </> file)) 70 + >|= List.concat 71 + 72 + let crl_of_pem path = 73 + catch_invalid_arg 74 + (read_file path >|= fun data -> 75 + match X509.CRL.decode_der data with 76 + | Ok cs -> cs 77 + | Error (`Msg m) -> invalid_arg ("failed to parse CRL " ^ m)) 78 + (o failure @@ Printf.sprintf "CRL in %s: %s" path) 79 + 80 + let crls_of_pem_dir = function 81 + | None -> Lwt.return None 82 + | Some path -> 83 + read_dir path >>= fun files -> 84 + Lwt_list.map_p (fun file -> crl_of_pem (path </> file)) files >|= fun crls -> 85 + Some crls 86 + 87 + let authenticator ?allowed_hashes ?crls param = 88 + let time () = Some (Ptime_clock.now ()) in 89 + let of_cas cas = 90 + crls_of_pem_dir crls >|= fun crls -> 91 + X509.Authenticator.chain_of_trust ?allowed_hashes ?crls ~time cas 92 + and dotted_hex_to_cs hex = 93 + Ohex.decode (String.map (function ':' -> ' ' | x -> x) hex) 94 + and fingerp hash fingerprint = 95 + X509.Authenticator.key_fingerprint ~time ~hash ~fingerprint 96 + and cert_fingerp hash fingerprint = 97 + X509.Authenticator.cert_fingerprint ~time ~hash ~fingerprint 98 + in 99 + match param with 100 + | `Ca_file path -> certs_of_pem path >>= of_cas 101 + | `Ca_dir path -> certs_of_pem_dir path >>= of_cas 102 + | `Key_fingerprint (hash, fp) -> return (fingerp hash fp) 103 + | `Hex_key_fingerprint (hash, fp) -> 104 + let fp = dotted_hex_to_cs fp in 105 + return (fingerp hash fp) 106 + | `Cert_fingerprint (hash, fp) -> return (cert_fingerp hash fp) 107 + | `Hex_cert_fingerprint (hash, fp) -> 108 + let fp = dotted_hex_to_cs fp in 109 + return (cert_fingerp hash fp)
+26
vendor/opam/tls/lwt/x509_lwt.mli
··· 1 + (** X.509 certificate handling using Lwt. *) 2 + 3 + (** [private_of_pems ~cert ~priv_key] is [priv], after reading the 4 + private key and certificate chain from the given PEM-encoded 5 + files. *) 6 + val private_of_pems : cert:Lwt_io.file_name -> priv_key:Lwt_io.file_name -> Tls.Config.certchain Lwt.t 7 + 8 + (** [certs_of_pem file] is [certificates], which are read from the 9 + PEM-encoded [file]. *) 10 + val certs_of_pem : Lwt_io.file_name -> X509.Certificate.t list Lwt.t 11 + 12 + (** [certs_of_pem_dir dir] is [certificates], which are read from all 13 + PEM-encoded files in [dir]. *) 14 + val certs_of_pem_dir : Lwt_io.file_name -> X509.Certificate.t list Lwt.t 15 + 16 + (** [authenticator methods] constructs an [authenticator] using the 17 + specified method and data. *) 18 + val authenticator : ?allowed_hashes:Digestif.hash' list -> ?crls:Lwt_io.file_name -> 19 + [ `Ca_file of Lwt_io.file_name 20 + | `Ca_dir of Lwt_io.file_name 21 + | `Key_fingerprint of Digestif.hash' * string 22 + | `Hex_key_fingerprint of Digestif.hash' * string 23 + | `Cert_fingerprint of Digestif.hash' * string 24 + | `Hex_cert_fingerprint of Digestif.hash' * string 25 + ] 26 + -> X509.Authenticator.t Lwt.t
+4
vendor/opam/tls/miou/dune
··· 1 + (library 2 + (name tls_miou_unix) 3 + (public_name tls-miou-unix) 4 + (libraries miou.unix tls))
+15
vendor/opam/tls/miou/tests/dune
··· 1 + (test 2 + (name fuzz) 3 + (package tls-miou-unix) 4 + (libraries 5 + mirage-crypto-rng-miou-unix 6 + ohex 7 + rresult 8 + ptime 9 + ptime.clock.os 10 + crowbar 11 + hxd.core 12 + hxd.string 13 + tls-miou-unix) 14 + (instrumentation 15 + (backend bisect_ppx)))
+339
vendor/opam/tls/miou/tests/fuzz.ml
··· 1 + let rec random_path ?(tries = 10) fmt = 2 + if tries <= 0 then failwith "Impossible to generate an available random path"; 3 + let res = Bytes.create 6 in 4 + for i = 0 to Bytes.length res - 1 do 5 + let chr = 6 + match Random.int (10 + 26 + 26) with 7 + | n when n < 10 -> Char.chr (Char.code '0' + n) 8 + | n when n < 10 + 26 -> Char.chr (Char.code 'a' + n - 10) 9 + | n -> Char.chr (Char.code 'A' + n - 10 - 26) 10 + in 11 + Bytes.set res i chr 12 + done; 13 + let path = Fmt.str fmt (Bytes.unsafe_to_string res) in 14 + if Sys.file_exists path then random_path ~tries:(pred tries) fmt else path 15 + 16 + let unlink_if_exists path = 17 + try Unix.unlink path with Unix.Unix_error (Unix.ENOENT, _, _) -> () 18 + 19 + let bind_and_listen ?(backlog = 16) () = 20 + let tmp = random_path "socket-%s.socket" in 21 + unlink_if_exists tmp; 22 + let socket = Unix.socket ~cloexec:true Unix.PF_UNIX Unix.SOCK_STREAM 0 in 23 + let addr = Unix.ADDR_UNIX tmp in 24 + Unix.bind socket addr; 25 + Unix.listen socket backlog; 26 + (Miou_unix.of_file_descr ~non_blocking:true socket, addr, tmp) 27 + 28 + module Ca = struct 29 + open Rresult 30 + 31 + let prefix = 32 + X509.Distinguished_name. 33 + [ Relative_distinguished_name.singleton (CN "Fuzzer") ] 34 + 35 + let cacert_dn = 36 + X509.Distinguished_name.( 37 + prefix 38 + @ [ Relative_distinguished_name.singleton (CN "Ephemeral CA for fuzzer") ]) 39 + 40 + let cacert_lifetime = Ptime.Span.v (365, 0L) 41 + let _10s = Ptime.Span.of_int_s 10 42 + 43 + let make domain_name seed = 44 + let valid_from = Option.get Ptime.(sub_span (v (Ptime_clock.now_d_ps ())) _10s) in 45 + Domain_name.of_string domain_name >>= Domain_name.host 46 + >>= fun domain_name -> 47 + let private_key = 48 + let seed = Base64.decode_exn ~pad:false seed in 49 + let g = Mirage_crypto_rng.(create ~seed (module Fortuna)) in 50 + Mirage_crypto_pk.Rsa.generate ~g ~bits:2048 () 51 + in 52 + Ptime.add_span valid_from cacert_lifetime 53 + |> Option.to_result ~none:(R.msgf "End time out of range") 54 + >>= fun valid_until -> 55 + X509.Signing_request.create cacert_dn (`RSA private_key) >>= fun ca_csr -> 56 + let extensions = 57 + let open X509.Extension in 58 + let key_id = 59 + X509.Public_key.id X509.Signing_request.((info ca_csr).public_key) 60 + in 61 + empty 62 + |> add Subject_alt_name 63 + ( true, 64 + X509.General_name.( 65 + singleton DNS [ Domain_name.to_string domain_name ]) ) 66 + |> add Basic_constraints (true, (false, None)) 67 + |> add Key_usage 68 + (true, [ `Digital_signature; `Content_commitment; `Key_encipherment ]) 69 + |> add Subject_key_id (false, key_id) 70 + in 71 + X509.Signing_request.sign ~valid_from ~valid_until ~extensions 72 + ca_csr (`RSA private_key) cacert_dn 73 + |> R.reword_error (R.msgf "%a" X509.Validation.pp_signature_error) 74 + >>= fun certificate -> 75 + let fingerprint = X509.Certificate.fingerprint `SHA256 certificate in 76 + let time () = Some (Ptime_clock.now ()) in 77 + let authenticator = 78 + X509.Authenticator.cert_fingerprint ~time ~hash:`SHA256 79 + ~fingerprint 80 + in 81 + Ok (certificate, `RSA private_key, authenticator) 82 + end 83 + 84 + let fuzz_coop = "fuzz.coop" 85 + let mutex = Miou.Mutex.create () 86 + let epr fmt = Miou.Mutex.protect mutex @@ fun () -> Fmt.epr fmt 87 + 88 + type operation = 89 + | Send of string 90 + | Recv of int 91 + | Shutdown of [ `read | `write ] 92 + | Close 93 + | Noop 94 + 95 + module Stop = struct 96 + type t = { 97 + mutex : Miou.Mutex.t; 98 + condition : Miou.Condition.t; 99 + mutable stop : bool; 100 + } 101 + 102 + let create () = 103 + let mutex = Miou.Mutex.create () in 104 + let condition = Miou.Condition.create () in 105 + { mutex; condition; stop = false } 106 + 107 + let stop t = 108 + Miou.Mutex.protect t.mutex @@ fun () -> 109 + t.stop <- true; 110 + Miou.Condition.broadcast t.condition 111 + 112 + let wait t = 113 + Miou.Mutex.protect t.mutex @@ fun () -> 114 + while t.stop = false do 115 + Miou.Condition.wait t.condition t.mutex 116 + done 117 + end 118 + 119 + let inhibit fn = try fn () with _exn -> () 120 + 121 + let run ~role:_ actions tls = 122 + let rec go buf tls = function 123 + | [] -> Buffer.contents buf 124 + | Noop :: actions -> 125 + Miou.yield (); 126 + go buf tls actions 127 + | Send str :: actions -> 128 + Tls_miou_unix.write tls str; 129 + go buf tls actions 130 + | Close :: actions -> 131 + Tls_miou_unix.close tls; 132 + go buf tls actions 133 + | Shutdown cmd :: actions -> 134 + Tls_miou_unix.shutdown tls (cmd :> [ `read | `write | `read_write ]); 135 + go buf tls actions 136 + | Recv len :: actions -> 137 + let tmp = Bytes.make len '\000' in 138 + Tls_miou_unix.really_read tls tmp; 139 + Buffer.add_subbytes buf tmp 0 len; 140 + go buf tls actions 141 + in 142 + let buf = Buffer.create 0x100 in 143 + try go buf tls actions with 144 + | End_of_file | Tls_miou_unix.Closed_by_peer | Tls_miou_unix.Tls_alert _ 145 + | Tls_miou_unix.Tls_failure _ -> 146 + inhibit (fun () -> Miou_unix.close (Tls_miou_unix.file_descr tls)); 147 + Buffer.contents buf 148 + | exn -> 149 + inhibit (fun () -> Miou_unix.close (Tls_miou_unix.file_descr tls)); 150 + raise exn 151 + 152 + let run_client ~to_client:actions cfg addr = 153 + let domain = Unix.domain_of_sockaddr addr in 154 + let socket = Unix.socket ~cloexec:true domain Unix.SOCK_STREAM 0 in 155 + Unix.connect socket addr; 156 + let fd = Miou_unix.of_file_descr ~non_blocking:true socket in 157 + let tls = Tls_miou_unix.client_of_fd cfg fd in 158 + let finally () = 159 + inhibit (fun () -> Unix.close socket) 160 + in 161 + Fun.protect ~finally @@ fun () -> run ~role:"client" actions tls 162 + 163 + let rec cleanup orphans clients = 164 + match Miou.care orphans with 165 + | None | Some None -> clients 166 + | Some (Some prm) -> 167 + let clients = Miou.await prm :: clients in 168 + cleanup orphans clients 169 + 170 + let rec terminate orphans clients = 171 + match Miou.care orphans with 172 + | None -> List.rev clients 173 + | Some None -> 174 + Miou.yield (); 175 + terminate orphans clients 176 + | Some (Some prm) -> 177 + let clients = Miou.await prm :: clients in 178 + terminate orphans clients 179 + 180 + exception Stop 181 + 182 + let run_server ~to_server:actions ~stop fd cfg = 183 + let rec go orphans clients = 184 + let clients = cleanup orphans clients in 185 + let accept = Miou.async @@ fun () -> Miou_unix.accept ~cloexec:true fd in 186 + let stop = 187 + Miou.async @@ fun () -> 188 + Stop.wait stop; 189 + raise Stop 190 + in 191 + match Miou.await_first [ accept; stop ] with 192 + | Error _ -> 193 + inhibit (fun () -> Miou_unix.close fd); 194 + terminate orphans clients 195 + | Ok (fd, _) -> 196 + ignore 197 + ( Miou.async ~orphans @@ fun () -> 198 + match Tls_miou_unix.server_of_fd cfg fd with 199 + | tls -> 200 + let str = run ~role:"server" actions tls in 201 + inhibit (fun () -> Miou_unix.close fd); str 202 + | exception _ -> 203 + Miou_unix.close fd; 204 + String.empty ); 205 + go orphans clients 206 + in 207 + go (Miou.orphans ()) [] 208 + 209 + let compile to_client to_server = 210 + let close_client close = function 211 + | Close -> close lor 0b1100 212 + | Shutdown `read -> close lor 0b1000 213 + | Shutdown `write -> close lor 0b0100 214 + | _ -> close 215 + in 216 + let close_server close = function 217 + | Close -> close lor 0b0011 218 + | Shutdown `read -> close lor 0b0010 219 + | Shutdown `write -> close lor 0b0001 220 + | _ -> close 221 + in 222 + let client = Buffer.create 0x100 in 223 + let server = Buffer.create 0x100 in 224 + let rec go close to_client to_server = 225 + match (close, to_client, to_server) with 226 + | _, [], _ | _, _, [] -> () 227 + | close, ((Shutdown _ | Close) as operation) :: to_client, _ -> 228 + go (close_client close operation) to_client to_server 229 + | close, _, ((Shutdown _ | Close) as operation) :: to_server -> 230 + go (close_server close operation) to_client to_server 231 + | close, Noop :: to_client, to_server | close, to_client, Noop :: to_server 232 + -> 233 + go close to_client to_server 234 + | close, Send str :: to_client, Recv n :: to_server -> 235 + assert (String.length str = n); 236 + if close land 0b0100 = 0 && close land 0b0010 = 0 then 237 + Buffer.add_string server str; 238 + if close land 0b0100 = 0 && close land 0b0010 = 0 then 239 + go close to_client to_server 240 + | close, Recv n :: to_client, Send str :: to_server -> 241 + assert (String.length str = n); 242 + if close land 0b1000 = 0 && close land 0b0001 = 0 then 243 + Buffer.add_string client str; 244 + if close land 0b1000 = 0 && close land 0b0001 = 0 then 245 + go close to_client to_server 246 + | _, Send _ :: _, Send _ :: _ | _, Recv _ :: _, Recv _ :: _ -> 247 + assert false (* GADT? *) 248 + in 249 + go 0x0 to_client to_server; 250 + (Buffer.contents client, Buffer.contents server) 251 + 252 + let pp_exn ppf exn = Fmt.string ppf (Printexc.to_string exn) 253 + let pp_str ppf str = Hxd_string.pp Hxd.default ppf str 254 + 255 + let run seed operations = 256 + Miou_unix.run ~domains:1 @@ fun () -> 257 + let rng = Mirage_crypto_rng_miou_unix.(initialize (module Pfortuna)) in 258 + let fd, addr, path = bind_and_listen () in 259 + let finally () = Unix.unlink path in 260 + Fun.protect ~finally @@ fun () -> 261 + let cert, pk, authenticator = 262 + Rresult.R.failwith_error_msg (Ca.make fuzz_coop seed) 263 + in 264 + let cfg_server = 265 + Result.get_ok (Tls.Config.server ~certificates:(`Single ([ cert ], pk)) ()) 266 + in 267 + let cfg_client = Result.get_ok (Tls.Config.client ~authenticator ()) in 268 + let to_client, to_server = List.split operations in 269 + let stop = Stop.create () in 270 + let prm0 = Miou.async @@ fun () -> run_server ~to_server ~stop fd cfg_server in 271 + let prm1 = 272 + Miou.async @@ fun () -> 273 + let finally () = Stop.stop stop in 274 + Fun.protect ~finally @@ fun () -> run_client ~to_client cfg_client addr 275 + in 276 + let send_to_client, send_to_server = compile to_client to_server in 277 + match (Miou.await prm0, Miou.await prm1) with 278 + | Ok [ Ok send_to_server' ], Ok send_to_client' -> 279 + Crowbar.check (String.equal send_to_client send_to_client'); 280 + Crowbar.check (String.equal send_to_server send_to_server'); 281 + let n = String.length send_to_client in 282 + let m = String.length send_to_server in 283 + Mirage_crypto_rng_miou_unix.kill rng; 284 + epr "[%a] %db %db transmitted\n%!" Fmt.(styled `Green string) "OK" n m 285 + | a, b -> 286 + Mirage_crypto_rng_miou_unix.kill rng; 287 + Crowbar.failf "[%a] Unexpected result: %a & %a\n%!" 288 + Fmt.(styled `Red string) "ERROR" 289 + Fmt.(Dump.result ~error:pp_exn ~ok:Fmt.(Dump.list (Dump.result ~error:pp_exn ~ok:pp_str))) a 290 + Fmt.(Dump.result ~error:pp_exn ~ok:pp_str) b 291 + 292 + let label name gen = Crowbar.with_printer Fmt.(const string name) gen 293 + 294 + let direction = 295 + let open Crowbar in 296 + choose 297 + [ 298 + label "server-to-client" (const `To_client); 299 + label "client-to-server" (const `To_server); 300 + ] 301 + 302 + let shutdown = 303 + let open Crowbar in 304 + choose 305 + [ 306 + label "close" (const Close); 307 + label "shutdown-recv" (const (Shutdown `read)); 308 + label "shutdown-send" (const (Shutdown `write)); 309 + label "noop" (const Noop); 310 + ] 311 + 312 + let operation = 313 + let open Crowbar in 314 + map [ direction; bytes ] @@ fun direction str -> 315 + match (direction, str) with 316 + | _, "" -> (Noop, Noop) 317 + | `To_server, str -> (Send str, Recv (String.length str)) 318 + | `To_client, str -> (Recv (String.length str), Send str) 319 + 320 + let counter = Atomic.make 0 321 + 322 + let operations = 323 + let open Crowbar in 324 + fix @@ fun m -> 325 + let continue (to_client, to_server) = 326 + if Atomic.fetch_and_add counter 1 >= 4 then const [ (Close, Close) ] 327 + else map [ m ] @@ fun ops -> (to_client, to_server) :: ops 328 + in 329 + map 330 + [ list1 operation; dynamic_bind (pair shutdown shutdown) continue ] 331 + List.rev_append 332 + 333 + let seed = Crowbar.(map [ bytes ] Base64.encode_exn) 334 + 335 + let () = 336 + Sys.set_signal Sys.sigpipe Sys.Signal_ignore; 337 + Crowbar.add_test ~name:"run" Crowbar.[ seed; operations ] @@ fun seed operations -> 338 + run seed operations; 339 + Atomic.set counter 0
+332
vendor/opam/tls/miou/tls_miou_unix.ml
··· 1 + (* NOTE: the unix/tls_unix.ml is mostly copied from here, so any change should be synchronized. *) 2 + 3 + let src = Logs.Src.create "tls-miou" 4 + 5 + module Log = (val Logs.src_log src : Logs.LOG) 6 + 7 + external reraise : exn -> 'a = "%reraise" 8 + 9 + let ( $ ) f x = f x 10 + 11 + exception Tls_alert of Tls.Packet.alert_type 12 + exception Tls_failure of Tls.Engine.failure 13 + exception Closed_by_peer 14 + 15 + let () = 16 + Printexc.register_printer @@ function 17 + | Closed_by_peer -> Some "Connection closed by peer" 18 + | Tls_alert alert -> Some (Tls.Packet.alert_type_to_string alert) 19 + | Tls_failure failure -> Some (Tls.Engine.string_of_failure failure) 20 + | _ -> None 21 + 22 + type state = 23 + [ `Active of Tls.Engine.state 24 + | `Read_closed of Tls.Engine.state 25 + | `Write_closed of Tls.Engine.state 26 + | `Closed 27 + | `Error of exn ] 28 + 29 + type t = { 30 + role : [ `Server | `Client ]; 31 + fd : Miou_unix.file_descr; 32 + mutable state : state; 33 + mutable linger : string option; 34 + read_buffer_size : int; 35 + buf : bytes; 36 + mutable rd_closed : bool; 37 + } 38 + 39 + let file_descr { fd; _ } = fd 40 + 41 + let half_close state mode = 42 + match (state, mode) with 43 + | `Active tls, `read -> `Read_closed tls 44 + | `Active tls, `write -> `Write_closed tls 45 + | `Active _, `read_write -> `Closed 46 + | `Read_closed tls, `read -> `Read_closed tls 47 + | `Read_closed _, (`write | `read_write) -> `Closed 48 + | `Write_closed tls, `write -> `Write_closed tls 49 + | `Write_closed _, (`read | `read_write) -> `Closed 50 + | ((`Closed | `Error _) as e), (`read | `write | `read_write) -> e 51 + 52 + let inject_state tls = function 53 + | `Active _ -> `Active tls 54 + | `Read_closed _ -> `Read_closed tls 55 + | `Write_closed _ -> `Write_closed tls 56 + | (`Closed | `Error _) as e -> e 57 + 58 + let tls_alert a = Tls_alert a 59 + let tls_fail f = Tls_failure f 60 + let inhibit fn v = try fn v with _ -> () 61 + 62 + let write flow str = 63 + Log.debug (fun m -> m "try to write %d byte(s)" (String.length str)); 64 + try Miou_unix.write flow.fd str with 65 + | Unix.Unix_error ((Unix.EPIPE | Unix.ECONNRESET), _, _) -> 66 + flow.state <- half_close flow.state `write; 67 + raise Closed_by_peer 68 + | Unix.Unix_error (_, _, _) as exn -> 69 + flow.state <- `Error exn; 70 + reraise exn 71 + 72 + let handle flow tls str = 73 + match Tls.Engine.handle_tls tls str with 74 + | Ok (state, eof, `Response resp, `Data data) -> 75 + Log.debug (fun m -> m "We handled %d byte(s)" (String.length str)); 76 + let state = inject_state state flow.state in 77 + let state = Option.(value ~default:state (map (fun `Eof -> half_close state `read) eof)) in 78 + flow.state <- state; 79 + let to_close = flow.state = `Closed in 80 + Option.iter (inhibit $ write flow) resp; 81 + (* NOTE(dinosaure): [write flow] can set [flow.state]. So we must 82 + check if the actual [flow.state] or the [flow.state] after [write flow] 83 + want to close the underlying file-descriptor. *) 84 + if to_close || flow.state = `Closed then Miou_unix.close flow.fd; 85 + data 86 + | Error (fail, `Response resp) -> 87 + let exn = match fail with 88 + | `Alert a -> tls_alert a | f -> tls_fail f in 89 + flow.state <- `Error exn; 90 + let _ = inhibit (write flow) resp in 91 + raise exn 92 + 93 + let read flow = 94 + match Miou_unix.read flow.fd flow.buf ~off:0 ~len:(Bytes.length flow.buf) with 95 + | 0 -> Ok String.empty 96 + | len -> Ok (Bytes.sub_string flow.buf 0 len) 97 + | exception Unix.Unix_error (Unix.ECONNRESET, _, _) -> Ok String.empty 98 + | exception exn -> Error exn 99 + 100 + let not_errored = function `Error _ -> false | _ -> true 101 + 102 + let garbage flow = match flow.linger with 103 + | Some "" | None -> false 104 + | _ -> true 105 + 106 + let read_react flow = 107 + match flow.state with 108 + | `Error exn -> raise exn 109 + | `Read_closed _ | `Closed when garbage flow -> 110 + (* XXX(dinosaure): [`Closed] can appear "at the same time" than some 111 + application-data. In that case, we stored them into [t.linger]. Depending 112 + on who closed the connection, [read_react] gives this /garbage/ in any 113 + situation (even if the user closed the connection). 114 + 115 + An extra layer with [read] below check if [`Read_closed]/[`Close] comes 116 + from the network (the peer closed the connection) or the user. In the 117 + first case, we must give pending application-data. In the second case, 118 + we must return [0] (or raise [End_of_file]). *) 119 + let mbuf = flow.linger in 120 + flow.linger <- None; 121 + mbuf 122 + | `Read_closed _ | `Closed -> 123 + (* XXX(dinosaure): the goal of [read_react] is to read some encrypted bytes 124 + and try to decrypt them with [handle]. If the linger is empty, this means 125 + that we're trying to get more data (to decrypt) when we can't get any 126 + more. From this point of view, it's an error that needs to be notified. 127 + However, this error can be interpreted in 2 ways: 128 + - we want to have more data decrypted. In this case, this error is 129 + expected and may result in the user being told that there is nothing 130 + left to read (for example, returning 0). 131 + - we attempt a handshake. In this case, we are dealing with an unexpected 132 + error. *) 133 + raise End_of_file 134 + | `Active _ | `Write_closed _ -> 135 + Log.debug (fun m -> m "read something from the TLS session"); 136 + match read flow with 137 + | Error exn -> 138 + if not_errored flow.state then flow.state <- `Error exn; 139 + raise exn 140 + | Ok "" -> 141 + (* XXX(dinosaure): see [`Read_closed _ | `Closed] case. *) 142 + raise End_of_file 143 + | Ok str -> 144 + Log.debug (fun m -> m "got %d byte(s)" (String.length str)); 145 + match flow.state with 146 + | `Active tls | `Read_closed tls | `Write_closed tls -> handle flow tls str 147 + | `Closed -> raise End_of_file 148 + | `Error exn -> raise exn 149 + [@@ocamlformat "disable"] 150 + 151 + let rec read_in flow ?(off= 0) ?len buf = 152 + let len = Option.value ~default:(Bytes.length buf - off) len in 153 + let write_in res = 154 + let rlen = String.length res in 155 + let mlen = min len rlen in 156 + Bytes.blit_string res 0 buf off mlen; 157 + let linger = if mlen < rlen 158 + then Some (String.sub res mlen (rlen - mlen)) 159 + else None in 160 + flow.linger <- linger; mlen 161 + in 162 + match flow.linger with 163 + | Some res -> write_in res 164 + | None -> ( 165 + match read_react flow with 166 + | None -> read_in ~off ~len flow buf 167 + | Some res -> write_in res) 168 + 169 + let writev flow bufs = 170 + match flow.state with 171 + | `Closed | `Write_closed _ -> raise Closed_by_peer 172 + | `Error exn -> reraise exn 173 + | `Active tls | `Read_closed tls -> ( 174 + match Tls.Engine.send_application_data tls bufs with 175 + | Some (tls, answer) -> 176 + flow.state <- inject_state tls flow.state; 177 + write flow answer 178 + | None -> assert false) 179 + 180 + let rec drain_handshake flow = 181 + let push_linger flow mcs = 182 + match (mcs, flow.linger) with 183 + | None, _ -> () 184 + | scs, None -> flow.linger <- scs 185 + | Some cs, Some l -> flow.linger <- Some (l ^ cs) 186 + in 187 + match flow.state with 188 + | `Active tls when not (Tls.Engine.handshake_in_progress tls) -> flow 189 + | (`Read_closed _ | `Closed) when garbage flow -> flow 190 + | _ -> 191 + Log.debug (fun m -> m "start to read something from the TLS session"); 192 + let mcs = read_react flow in 193 + push_linger flow mcs; 194 + drain_handshake flow 195 + 196 + let close flow = 197 + match flow.state with 198 + | `Active tls | `Read_closed tls -> 199 + let tls, str = Tls.Engine.send_close_notify tls in 200 + flow.rd_closed <- true; 201 + flow.state <- inject_state tls flow.state; 202 + flow.state <- `Closed; 203 + inhibit (write flow) str; 204 + Miou_unix.close flow.fd 205 + | `Write_closed _ -> 206 + flow.rd_closed <- true; 207 + flow.state <- `Closed; 208 + Miou_unix.close flow.fd 209 + | `Closed -> flow.rd_closed <- true 210 + | `Error _ -> 211 + flow.rd_closed <- true; 212 + Miou_unix.close flow.fd 213 + 214 + let closed_by_user flow = function 215 + | `read | `read_write -> flow.rd_closed <- true 216 + | `write -> () 217 + 218 + let shutdown flow mode = 219 + closed_by_user flow mode; 220 + match (flow.state, mode) with 221 + | `Active tls, `read -> 222 + Log.debug (fun m -> m "shutdown `read"); 223 + flow.state <- inject_state tls (half_close flow.state mode) 224 + | (`Active tls | `Read_closed tls), (`write | `read_write) -> 225 + let tls, str = Tls.Engine.send_close_notify tls in 226 + flow.state <- inject_state tls (half_close flow.state mode); 227 + (* NOTE(dinosaure): [write flow] can set [flow.state]. So we must 228 + check if the actual [flow.state] or the [flow.state] after [write flow] 229 + want to close the underlying file-descriptor. *) 230 + let to_close = flow.state = `Closed in 231 + inhibit (write flow) str; 232 + if to_close || flow.state = `Closed then Miou_unix.close flow.fd 233 + | `Write_closed tls, (`read | `read_write) -> 234 + flow.state <- inject_state tls (half_close flow.state mode); 235 + if flow.state = `Closed then Miou_unix.close flow.fd 236 + | `Error _, _ -> Miou_unix.close flow.fd 237 + | `Read_closed _, `read -> () 238 + | `Write_closed _, `write -> () 239 + | `Closed, _ -> () 240 + 241 + let client_of_fd conf ?(read_buffer_size = 0x1000) ?host fd = 242 + let conf' = 243 + match host with None -> conf | Some host -> Tls.Config.peer conf host 244 + in 245 + let tls, init = Tls.Engine.client conf' in 246 + let tls_flow = 247 + { 248 + role = `Client; 249 + fd; 250 + state = `Active tls; 251 + linger = None; 252 + read_buffer_size; 253 + buf = Bytes.make read_buffer_size '\000'; 254 + rd_closed = false; 255 + } 256 + in 257 + write tls_flow init; 258 + drain_handshake tls_flow 259 + 260 + let server_of_fd conf ?(read_buffer_size = 0x1000) fd = 261 + let tls = Tls.Engine.server conf in 262 + let tls_flow = 263 + { 264 + role = `Server; 265 + fd; 266 + state = `Active tls; 267 + linger = None; 268 + read_buffer_size; 269 + buf = Bytes.make read_buffer_size '\000'; 270 + rd_closed = false; 271 + } 272 + in 273 + drain_handshake tls_flow 274 + 275 + let write flow ?(off = 0) ?len str = 276 + let len = Option.value ~default:(String.length str - off) len in 277 + if off < 0 || len < 0 || off > String.length str - len 278 + then invalid_arg "Tls_miou.write"; 279 + if len > 0 then writev flow [ String.sub str off len ] 280 + 281 + let read t ?(off= 0) ?len buf = 282 + let len = Option.value ~default:(Bytes.length buf - off) len in 283 + if off < 0 || len < 0 || off > Bytes.length buf - len 284 + then invalid_arg "Tls_miou.read"; 285 + if t.rd_closed then 0 286 + else try read_in t ~off ~len buf with End_of_file -> 0 287 + 288 + let rec really_read_go t off len buf = 289 + let len' = read t buf ~off ~len in 290 + if len' == 0 then raise End_of_file 291 + else if len - len' > 0 292 + then really_read_go t (off + len') (len - len') buf 293 + 294 + let really_read t ?(off= 0) ?len buf = 295 + let len = Option.value ~default:(Bytes.length buf - off) len in 296 + if off < 0 || len < 0 || off > Bytes.length buf - len 297 + then invalid_arg "Tls_miou.really_read"; 298 + if len > 0 then really_read_go t off len buf 299 + 300 + let resolve host service = 301 + let tcp = Unix.getprotobyname "tcp" in 302 + match Unix.getaddrinfo host service [ AI_PROTOCOL tcp.p_proto ] with 303 + | [] -> Fmt.invalid_arg "No address for %s:%s" host service 304 + | ai :: _ -> ai.ai_addr 305 + 306 + let connect authenticator (v, port) = 307 + let conf = 308 + match Tls.Config.client ~authenticator () with 309 + | Ok config -> config 310 + | Error `Msg msg -> Fmt.invalid_arg "Configuration failure: %s" msg 311 + in 312 + let addr = resolve v (string_of_int port) in 313 + let fd = 314 + match addr with 315 + | Unix.ADDR_UNIX _ -> invalid_arg "Tls_miou.connect: Invalid UNIX socket" 316 + | Unix.ADDR_INET (inet_addr, _) -> 317 + if Unix.is_inet6_addr inet_addr then Miou_unix.tcpv6 () 318 + else Miou_unix.tcpv4 () 319 + in 320 + let host = Result.to_option Domain_name.(Result.bind (of_string v) host) in 321 + match Miou_unix.connect fd addr with 322 + | () -> client_of_fd conf ?host fd 323 + | exception exn -> 324 + Miou_unix.close fd; 325 + raise exn 326 + 327 + let epoch flow = match flow.state with 328 + | `Active tls | `Read_closed tls | `Write_closed tls -> 329 + ( match Tls.Engine.epoch tls with 330 + | Error () -> assert false 331 + | Ok data -> Some data ) 332 + | _ -> None
+96
vendor/opam/tls/miou/tls_miou_unix.mli
··· 1 + (** Effectful operations using Miou for pure TLS. 2 + 3 + The pure TLS is state and buffer in, state and buffer out. This module uses 4 + Miou (and its Unix layer) for communication over the network. *) 5 + 6 + exception Tls_alert of Tls.Packet.alert_type 7 + exception Tls_failure of Tls.Engine.failure 8 + exception Closed_by_peer 9 + 10 + type t 11 + (** Abstract type of a session. *) 12 + 13 + val file_descr : t -> Miou_unix.file_descr 14 + (** [file_descr] returns the underlying file-descriptor used by the given 15 + TLS {i socket}. *) 16 + 17 + val read : t -> ?off:int -> ?len:int -> bytes -> int 18 + (** [read fd buf ~off ~len] reads up to [len] bytes (defaults to 19 + [Bytes.length buf - off] from the given TLS {i socket} [fd], storing them in 20 + byte sequence [buf], starting at position [off] in [buf] (defaults to [0]). 21 + It returns the actual number of characters read, between 0 and [len] 22 + (inclusive). 23 + 24 + @raise Unix_error raised by the system call {!val:Unix.read}. The function 25 + handles {!val:Unix.EINTR}, {!val:Unix.EAGAIN} and {!val:Unix.EWOULDBLOCK} 26 + exceptions and redo the system call. 27 + 28 + @raise Invalid_argument if [off] and [len] do not designate a valid range of 29 + [buf]. *) 30 + 31 + val really_read : t -> ?off:int -> ?len:int -> bytes -> unit 32 + (** [really_read fd buf ~off ~len] reads [len] bytes (defaults to 33 + [Bytes.length buf - off]) from the given TLS {i socket} [fd], storing them 34 + in byte sequence [buf], starting at position [off] in [buf] (defaults to 35 + [0]). If [len = 0], [really_read] does nothing. 36 + 37 + @raise Unix_error raised by the system call {!val:Unix.read}. The function 38 + handles {!val:Unix.EINTR}, {!val:Unix.EAGAIN} and {!val:Unix.EWOULDBLOCK} 39 + exceptions and redo the system call. 40 + 41 + @raise End_of_file if {!val:Unix.read} returns [0] before [len] characters 42 + have been read. 43 + 44 + @raise Invalid_argument if [off] and [len] do not designate a valid range of 45 + [buf]. *) 46 + 47 + val write : t -> ?off:int -> ?len:int -> string -> unit 48 + (** [write t str ~off ~len] writes [len] bytes (defaults to 49 + [String.length str - off]) from byte sequence [str], starting at offset 50 + [off] (defaults to [0]), to the given TLS {i socket} [fd]. 51 + 52 + @raise Unix_error raised by the syscall call {!val:Unix.write}. The function 53 + handles {!val:Unix.EINTR}, {!val:Unix.EAGAIN} and {!val:Unix.EWOULDBLOCK} 54 + exceptions and redo the system call. 55 + 56 + @raise Closed_by_peer if [t] is connected to a peer whose reading end is 57 + closed. Similar to the {!val:EPIPE} error for pipe/socket connected. 58 + 59 + @raise Invalid_argument if [off] and [len] do not designate a valid range of 60 + [buf]. *) 61 + 62 + val close : t -> unit 63 + (** [close flow] closes the TLS session and the underlying file-descriptor. *) 64 + 65 + val shutdown : t -> [ `read | `write | `read_write ] -> unit 66 + (** [shutdown t direction] closes the direction of the TLS session [t]. If 67 + [`read_write] or [`write] is closed, a TLS close-notify is sent to the other 68 + endpoint. If this results in a fully-closed session (or an errorneous 69 + session), the underlying file descriptor is closed. *) 70 + 71 + val client_of_fd : 72 + Tls.Config.client -> 73 + ?read_buffer_size:int -> 74 + ?host:[ `host ] Domain_name.t -> 75 + Miou_unix.file_descr -> 76 + t 77 + (** [client_of_flow client ~host fd] is [t], after client-side TLS handshake of 78 + [fd] using [client] configuration and [host]. 79 + 80 + @raise End_of_file if we are not able to complete the handshake. *) 81 + 82 + val server_of_fd : 83 + Tls.Config.server -> ?read_buffer_size:int -> Miou_unix.file_descr -> t 84 + (** [server_of_fd server fd] is [t], after server-side TLS handshake of [fd] 85 + using [server] configuration. 86 + 87 + @raise End_of_file if we are not able to complete the handshake. *) 88 + 89 + val connect : X509.Authenticator.t -> string * int -> t 90 + (** [connect authenticator (host, port)] is [t], a connected TLS connection 91 + to [host] on [port] using the default configuration and the 92 + [authenticator]. *) 93 + 94 + val epoch : t -> Tls.Core.epoch_data option 95 + (** [epoch t] returns [epoch], which contains information of the active 96 + session. *)
+5
vendor/opam/tls/mirage/dune
··· 1 + (library 2 + (name tls_mirage) 3 + (public_name tls-mirage) 4 + (wrapped false) 5 + (libraries tls lwt ptime mirage-flow mirage-kv mirage-ptime mirage-crypto mirage-crypto-pk))
+1
vendor/opam/tls/mirage/example/.gitignore
··· 1 + /static?.ml*
+32
vendor/opam/tls/mirage/example/config.ml
··· 1 + open Mirage 2 + 3 + let secrets_dir = "sekrit" 4 + 5 + let build = 6 + try 7 + match Sys.getenv "BUILD" with 8 + | "client" -> `Client 9 + | _ -> `Server 10 + with Not_found -> `Server 11 + 12 + let disk = generic_kv_ro secrets_dir 13 + 14 + let stack = generic_stackv4 default_network 15 + 16 + let packages = [ 17 + package ~sublibs:["mirage"] "tls" ; 18 + package ~sublibs:["lwt"] "logs" 19 + ] 20 + 21 + let server = 22 + foreign ~deps:[abstract nocrypto] ~packages "Unikernel.Server" @@ stackv4 @-> kv_ro @-> pclock @-> job 23 + 24 + let client = 25 + foreign ~deps:[abstract nocrypto] ~packages "Unikernel.Client" @@ stackv4 @-> kv_ro @-> pclock @-> job 26 + 27 + let () = 28 + match build with 29 + | `Server -> 30 + register "tls-server" [ server $ stack $ disk $ default_posix_clock ] 31 + | `Client -> 32 + register "tls-client" [ client $ stack $ disk $ default_posix_clock ]
+1
vendor/opam/tls/mirage/example/sekrit/ca-roots.crt
··· 1 + ../../../certificates/ca-root-nss-short.crt
+1
vendor/opam/tls/mirage/example/sekrit/server.key
··· 1 + ../../../certificates/server.key
+1
vendor/opam/tls/mirage/example/sekrit/server.pem
··· 1 + ../../../certificates/server.pem
+96
vendor/opam/tls/mirage/example/unikernel.ml
··· 1 + open Lwt.Infix 2 + 3 + let escape_data buf = String.escaped (Cstruct.to_string buf) 4 + 5 + let make_tracer dump = 6 + let traces = ref [] in 7 + let trace sexp = 8 + traces := Sexplib.Sexp.to_string_hum sexp :: !traces 9 + and flush () = 10 + let msgs = List.rev !traces in 11 + traces := [] ; 12 + Lwt_list.iter_s dump msgs in 13 + (trace, flush) 14 + 15 + module Server (S : Mirage_stack.V4) 16 + (KV : Mirage_kv.RO) 17 + (CL : Mirage_clock.PCLOCK) = 18 + struct 19 + 20 + module TLS = Tls_mirage.Make (S.TCPV4) 21 + module X509 = Tls_mirage.X509 (KV) (CL) 22 + 23 + let rec handle flush tls = 24 + TLS.read tls >>= fun res -> 25 + flush () >>= fun () -> 26 + match res with 27 + | Ok (`Data buf) -> 28 + Logs_lwt.info (fun p -> p "recv %s" (escape_data buf)) >>= fun () -> 29 + (TLS.write tls buf >>= function 30 + | Ok () -> handle flush tls 31 + | Error e -> Logs_lwt.err (fun p -> p "write error %a" TLS.pp_write_error e)) 32 + | Ok `Eof -> Logs_lwt.info (fun p -> p "eof from server") 33 + | Error e -> Logs_lwt.err (fun p -> p "read error %a" TLS.pp_error e) 34 + 35 + let accept conf k flow = 36 + let trace, flush_trace = 37 + make_tracer (fun s -> Logs_lwt.debug (fun p -> p "%s" s)) 38 + in 39 + Logs_lwt.info (fun p -> p "accepted.") >>= fun () -> 40 + TLS.server_of_flow ~trace conf flow >>= function 41 + | Ok tls -> Logs_lwt.info (fun p -> p "shook hands") >>= fun () -> k flush_trace tls 42 + | Error e -> Logs_lwt.err (fun p -> p "%a" TLS.pp_write_error e) 43 + 44 + let start stack kv _ _ = 45 + X509.certificate kv `Default >>= fun cert -> 46 + let conf = Tls.Config.server ~certificates:(`Single cert) () in 47 + S.listen_tcpv4 stack ~port:4433 (accept conf handle) ; 48 + S.listen stack 49 + 50 + end 51 + 52 + module Client (S : Mirage_stack.V4) 53 + (KV : Mirage_kv.RO) 54 + (CL : Mirage_clock.PCLOCK) = 55 + struct 56 + 57 + module TLS = Tls_mirage.Make (S.TCPV4) 58 + module X509 = Tls_mirage.X509 (KV) (CL) 59 + 60 + open Ipaddr 61 + 62 + let peer = ((V4.of_string_exn "127.0.0.1", 4433), "localhost") 63 + let peer = ((V4.of_string_exn "2.19.157.15", 443), "www.apple.com") 64 + let peer = ((V4.of_string_exn "74.125.195.103", 443), "www.google.com") 65 + let peer = ((V4.of_string_exn "10.0.0.1", 4433), "localhost") 66 + let peer = ((V4.of_string_exn "23.253.164.126", 443), "tls.openmirage.org") 67 + let peer = ((V4.of_string_exn "216.105.38.15", 443), "slashdot.org") 68 + let peer = ((V4.of_string_exn "46.43.42.136", 443), "mirage.io") 69 + let peer = ((V4.of_string_exn "198.167.222.205", 443), "hannes.nqsb.io") 70 + 71 + let initial = Cstruct.of_string @@ 72 + "GET / HTTP/1.1\r\nConnection: Close\r\nHost: " ^ snd peer ^ "\r\n\r\n" 73 + 74 + let chat tls = 75 + let rec dump () = 76 + TLS.read tls >>= function 77 + | Ok (`Data buf) -> Logs_lwt.info (fun p -> p "recv %s" (escape_data buf)) >>= dump 78 + | Ok `Eof -> Logs_lwt.info (fun p -> p "eof") 79 + | Error e -> Logs_lwt.err (fun p -> p "chat err %a" TLS.pp_error e) 80 + in 81 + TLS.write tls initial >>= function 82 + | Ok () -> dump () 83 + | Error e -> Logs_lwt.err (fun p -> p "write error %a" TLS.pp_write_error e) 84 + 85 + let start stack kv _clock _ = 86 + X509.authenticator kv `CAs >>= fun authenticator -> 87 + let conf = Tls.Config.client ~authenticator () in 88 + S.TCPV4.create_connection (S.tcpv4 stack) (fst peer) 89 + >>= function 90 + | Error e -> Logs_lwt.err (fun p -> p "%a" S.TCPV4.pp_error e) 91 + | Ok tcp -> 92 + TLS.client_of_flow conf ~host:(snd peer) tcp >>= function 93 + | Ok tls -> chat tls 94 + | Error e -> Logs_lwt.err (fun p -> p "%a" TLS.pp_write_error e) 95 + 96 + end
+17
vendor/opam/tls/mirage/example2/config.ml
··· 1 + open Mirage 2 + 3 + let secrets_dir = "sekrit" 4 + 5 + let disk = direct_kv_ro secrets_dir 6 + and stack = generic_stackv4 default_network 7 + 8 + let packages = [ 9 + package "cohttp-mirage" ; 10 + package ~min:"0.99" "cohttp-lwt" ; 11 + package ~sublibs:["mirage"] "tls" ; 12 + package "tcpip" ; 13 + ] 14 + let server = foreign ~deps:[abstract nocrypto] ~packages "Unikernel.Main" @@ stackv4 @-> kv_ro @-> pclock @-> job 15 + 16 + let () = 17 + register "tls-server" [ server $ stack $ disk $ default_posix_clock ]
+1
vendor/opam/tls/mirage/example2/sekrit/server.key
··· 1 + ../../../certificates/server.key
+1
vendor/opam/tls/mirage/example2/sekrit/server.pem
··· 1 + ../../../certificates/server.pem
+41
vendor/opam/tls/mirage/example2/unikernel.ml
··· 1 + open Lwt.Infix 2 + 3 + module Main (S : Mirage_stack.V4) 4 + (KV : Mirage_kv.RO) 5 + (CL : Mirage_clock.PCLOCK) = 6 + struct 7 + 8 + module TLS = Tls_mirage.Make (S.TCPV4) 9 + module X509 = Tls_mirage.X509 (KV) (CL) 10 + module Http = Cohttp_mirage.Server (TLS) 11 + 12 + module Body = Cohttp_lwt.Body 13 + 14 + let callback _conn req body = 15 + let resp = Cohttp.Response.make ~status:`OK () in 16 + (match Cohttp.Request.meth req with 17 + | `POST -> 18 + Body.to_string body >|= fun contents -> 19 + "<pre>" ^ contents ^ "</pre>" 20 + | _ -> Lwt.return "") >|= fun inlet -> 21 + let body = Body.of_string @@ 22 + "<html><head><title>ohai</title></head> \ 23 + <body><h3>Secure CoHTTP on-line.</h3>" 24 + ^ inlet ^ "</body></html>\r\n" 25 + in 26 + (resp, body) 27 + 28 + let upgrade conf tcp = 29 + TLS.server_of_flow conf tcp >>= function 30 + | Error _ -> Lwt.fail (Failure "tls init") 31 + | Ok tls -> 32 + let t = Http.make ~callback () in 33 + Http.listen t tls 34 + 35 + let start stack kv _ _ = 36 + X509.certificate kv `Default >>= fun cert -> 37 + let conf = Tls.Config.server ~certificates:(`Single cert) () in 38 + S.listen_tcpv4 stack ~port:4433 (upgrade conf) ; 39 + S.listen stack 40 + 41 + end
+299
vendor/opam/tls/mirage/tls_mirage.ml
··· 1 + open Lwt.Infix 2 + 3 + module Make (F : Mirage_flow.S) = struct 4 + 5 + type error = [ `Tls_alert of Tls.Packet.alert_type 6 + | `Tls_failure of Tls.Engine.failure 7 + | `Read of F.error 8 + | `Write of F.write_error ] 9 + 10 + type write_error = [ Mirage_flow.write_error | error ] 11 + 12 + let pp_error ppf = function 13 + | `Tls_failure f -> Tls.Engine.pp_failure ppf f 14 + | `Tls_alert a -> Fmt.string ppf @@ Tls.Packet.alert_type_to_string a 15 + | `Read e -> F.pp_error ppf e 16 + | `Write e -> F.pp_write_error ppf e 17 + 18 + let pp_write_error ppf = function 19 + | #Mirage_flow.write_error as e -> Mirage_flow.pp_write_error ppf e 20 + | #error as e -> pp_error ppf e 21 + 22 + type flow = { 23 + role : [ `Server | `Client ] ; 24 + flow : F.flow ; 25 + mutable state : [ `Active of Tls.Engine.state 26 + | `Read_closed of Tls.Engine.state 27 + | `Write_closed of Tls.Engine.state 28 + | `Closed 29 + | `Error of error ] ; 30 + mutable linger : string list ; 31 + } 32 + 33 + let half_close state mode = 34 + match state, mode with 35 + | `Active tls, `read -> `Read_closed tls 36 + | `Active tls, `write -> `Write_closed tls 37 + | `Active _, `read_write -> `Closed 38 + | `Read_closed tls, `read -> `Read_closed tls 39 + | `Read_closed _, (`write | `read_write) -> `Closed 40 + | `Write_closed tls, `write -> `Write_closed tls 41 + | `Write_closed _, (`read | `read_write) -> `Closed 42 + | (`Closed | `Error _) as e, (`read | `write | `read_write) -> e 43 + 44 + let inject_state tls = function 45 + | `Active _ -> `Active tls 46 + | `Read_closed _ -> `Read_closed tls 47 + | `Write_closed _ -> `Write_closed tls 48 + | (`Closed | `Error _) as e -> e 49 + 50 + let tls_alert a = `Error (`Tls_alert a) 51 + let tls_fail f = `Error (`Tls_failure f) 52 + 53 + let write_flow flow buf = 54 + F.write flow.flow (Cstruct.of_string buf) >>= function 55 + | Ok _ as o -> Lwt.return o 56 + | Error `Closed -> 57 + flow.state <- half_close flow.state `write; 58 + Lwt.return (Error (`Write `Closed)) 59 + | Error e -> 60 + flow.state <- `Error (`Write e); 61 + Lwt.return (Error (`Write e)) 62 + 63 + let read_react flow = 64 + let handle tls buf = 65 + match Tls.Engine.handle_tls tls buf with 66 + | Ok (state, eof, `Response resp, `Data data) -> 67 + let state = inject_state state flow.state in 68 + let state = Option.(value ~default:state (map (fun `Eof -> half_close state `read) eof)) in 69 + flow.state <- state; 70 + ( match resp with 71 + | None -> Lwt.return @@ Ok () 72 + | Some buf -> write_flow flow buf) >>= fun _ -> 73 + Lwt.return @@ `Ok (Option.map Cstruct.of_string data) 74 + | Error (fail, `Response resp) -> 75 + let reason = match fail with 76 + | `Alert a -> tls_alert a 77 + | f -> tls_fail f 78 + in 79 + flow.state <- reason ; 80 + F.write flow.flow (Cstruct.of_string resp) >>= fun _ -> 81 + Lwt.return reason 82 + in 83 + match flow.state with 84 + | `Error _ as e -> Lwt.return e 85 + | `Read_closed _ | `Closed -> Lwt.return `Eof 86 + | `Active _ | `Write_closed _ -> 87 + F.read flow.flow >>= function 88 + | Error e -> 89 + flow.state <- `Error (`Read e); 90 + Lwt.return (`Error (`Read e)) 91 + | Ok `Eof -> 92 + flow.state <- half_close flow.state `read; 93 + Lwt.return `Eof 94 + | Ok `Data buf -> match flow.state with 95 + | `Active tls | `Write_closed tls -> handle tls (Cstruct.to_string buf) 96 + | `Read_closed _ | `Closed -> Lwt.return `Eof 97 + | `Error _ as e -> Lwt.return e 98 + 99 + let rec read flow = 100 + match flow.linger with 101 + | [] -> 102 + ( read_react flow >>= function 103 + | `Ok None -> read flow 104 + | `Ok (Some buf) -> Lwt.return @@ Ok (`Data buf) 105 + | `Eof -> Lwt.return @@ Ok `Eof 106 + | `Error e -> Lwt.return @@ Error e ) 107 + | bufs -> 108 + flow.linger <- [] ; 109 + let str = String.concat "" (List.rev bufs) in 110 + Lwt.return @@ Ok (`Data (Cstruct.of_string str)) 111 + 112 + let writev flow bufs = 113 + match flow.state with 114 + | `Closed | `Write_closed _ -> Lwt.return @@ Error `Closed 115 + | `Error e -> Lwt.return @@ Error (e :> write_error) 116 + | `Active tls | `Read_closed tls -> 117 + let bufs = List.map Cstruct.to_string bufs in 118 + match Tls.Engine.send_application_data tls bufs with 119 + | Some (tls, answer) -> 120 + flow.state <- `Active tls ; 121 + write_flow flow answer 122 + | None -> 123 + (* "Impossible" due to handshake draining. *) 124 + assert false 125 + 126 + let write flow buf = writev flow [buf] 127 + 128 + (* 129 + * XXX bad XXX 130 + * This is a point that should particularly be protected from concurrent r/w. 131 + * Doing this before a `t` is returned is safe; redoing it during rekeying is 132 + * not, as the API client already sees the `t` and can mistakenly interleave 133 + * writes while this is in progress. 134 + * *) 135 + let rec drain_handshake flow = 136 + match flow.state with 137 + | `Active tls when not (Tls.Engine.handshake_in_progress tls) -> 138 + Lwt.return @@ Ok flow 139 + | _ -> 140 + (* read_react re-throws *) 141 + read_react flow >>= function 142 + | `Ok mbuf -> 143 + flow.linger <- Option.(to_list (map Cstruct.to_string mbuf)) @ flow.linger ; 144 + drain_handshake flow 145 + | `Error e -> Lwt.return @@ Error (e :> write_error) 146 + | `Eof -> Lwt.return @@ Error `Closed 147 + 148 + type wr_or_msg = [ write_error | `Msg of string ] 149 + 150 + let underlying flow = flow.flow 151 + 152 + let reneg ?authenticator ?acceptable_cas ?cert ?(drop = true) flow = 153 + match flow.state with 154 + | `Closed | `Write_closed _ | `Read_closed _ -> Lwt.return @@ Error `Closed 155 + | `Error e -> Lwt.return @@ Error (e :> wr_or_msg) 156 + | `Active tls -> 157 + match Tls.Engine.reneg ?authenticator ?acceptable_cas ?cert tls with 158 + | None -> Lwt.return (Error (`Msg "Renegotiation already in progress")) 159 + | Some (tls', buf) -> 160 + if drop then flow.linger <- [] ; 161 + flow.state <- `Active tls' ; 162 + write_flow flow buf >>= fun _ -> 163 + drain_handshake flow >|= function 164 + | Ok _ -> Ok () 165 + | Error e -> Error (e :> wr_or_msg) 166 + 167 + let key_update ?request flow = 168 + match flow.state with 169 + | `Closed | `Write_closed _ -> Lwt.return @@ Error `Closed 170 + | `Error e -> Lwt.return @@ Error (e :> wr_or_msg) 171 + | `Active tls | `Read_closed tls -> 172 + match Tls.Engine.key_update ?request tls with 173 + | Error _ -> Lwt.return (Error (`Msg "Key update failed")) 174 + | Ok (tls', buf) -> 175 + flow.state <- `Active tls' ; 176 + write_flow flow buf >|= function 177 + | Ok _ as o -> o 178 + | Error e -> Error (e :> wr_or_msg) 179 + 180 + let close flow = 181 + (match flow.state with 182 + | `Active tls | `Read_closed tls -> 183 + let tls, buf = Tls.Engine.send_close_notify tls in 184 + flow.state <- inject_state tls flow.state; 185 + flow.state <- `Closed; 186 + write_flow flow buf >|= fun _ -> 187 + () 188 + | `Write_closed _ -> 189 + flow.state <- `Closed; 190 + Lwt.return_unit 191 + | _ -> Lwt.return_unit) >>= fun () -> 192 + F.close flow.flow 193 + 194 + let shutdown flow mode = 195 + match flow.state with 196 + | `Active tls | `Read_closed tls | `Write_closed tls -> 197 + let tls, buf = 198 + match flow.state, mode with 199 + | (`Active tls | `Read_closed tls), (`write | `read_write) -> 200 + let tls, buf = Tls.Engine.send_close_notify tls in 201 + tls, Some buf 202 + | _, _ -> tls, None 203 + in 204 + flow.state <- inject_state tls (half_close flow.state mode); 205 + (* as outlined above, this may fail since the TCP flow may already be (half-)closed *) 206 + Option.fold 207 + ~none:Lwt.return_unit 208 + ~some:(fun b -> write_flow flow b >|= fun _ -> ()) 209 + buf >>= fun () -> 210 + (match flow.state with 211 + | `Closed -> F.close flow.flow 212 + | _ -> Lwt.return_unit) 213 + | `Error _ | `Closed -> 214 + F.close flow.flow 215 + 216 + let client_of_flow conf ?host flow = 217 + let conf' = match host with 218 + | None -> conf 219 + | Some host -> Tls.Config.peer conf host 220 + in 221 + let (tls, init) = Tls.Engine.client conf' in 222 + let tls_flow = { 223 + role = `Client ; 224 + flow = flow ; 225 + state = `Active tls ; 226 + linger = [] ; 227 + } in 228 + write_flow tls_flow init >>= fun _ -> 229 + drain_handshake tls_flow 230 + 231 + let server_of_flow conf flow = 232 + let tls_flow = { 233 + role = `Server ; 234 + flow = flow ; 235 + state = `Active (Tls.Engine.server conf) ; 236 + linger = [] ; 237 + } in 238 + drain_handshake tls_flow 239 + 240 + let epoch flow = 241 + match flow.state with 242 + | `Closed | `Error _ -> Error () 243 + | `Active tls | `Read_closed tls | `Write_closed tls -> Tls.Engine.epoch tls 244 + 245 + (* let create_connection t tls_params host (addr, port) = 246 + |+ XXX addr -> (host : string) +| 247 + TCP.create_connection t (addr, port) >>= function 248 + | `Error _ as e -> return e 249 + | `Ok flow -> client_of_tcp_flow tls_params host flow *) 250 + 251 + (* let listen_ssl t cert ~port callback = 252 + let cb flow = 253 + server_of_tcp_flow cert flow >>= callback in 254 + TCP.input t ~listeners:(fun p -> if p = port then Some cb else None) *) 255 + 256 + end 257 + 258 + module X509 (KV : Mirage_kv.RO) = struct 259 + 260 + let ca_roots_file = Mirage_kv.Key.v "ca-roots.crt" 261 + let default_cert = "server" 262 + 263 + let err_fail pp = function 264 + | Ok x -> Lwt.return x 265 + | Error e -> Fmt.kstr Lwt.fail_with "%a" pp e 266 + 267 + let pp_msg ppf = function `Msg m -> Fmt.string ppf m 268 + 269 + let decode_or_fail f cs = err_fail pp_msg (f cs) 270 + 271 + let read kv name = 272 + KV.get kv name >>= err_fail KV.pp_error >|= Cstruct.of_string 273 + 274 + let read_crl kv = function 275 + | None -> Lwt.return None 276 + | Some filename -> 277 + read kv (Mirage_kv.Key.v filename) >>= fun data -> 278 + err_fail pp_msg (X509.CRL.decode_der (Cstruct.to_string data)) >|= fun crl -> 279 + Some [ crl ] 280 + 281 + let authenticator ?allowed_hashes ?crl kv = 282 + let time () = Some (Mirage_ptime.now ()) in 283 + let now = Mirage_ptime.now () in 284 + read kv ca_roots_file >|= Cstruct.to_string >>= 285 + decode_or_fail X509.Certificate.decode_pem_multiple >>= fun cas -> 286 + let ta = X509.Validation.valid_cas ~time:now cas in 287 + read_crl kv crl >|= fun crls -> 288 + X509.Authenticator.chain_of_trust ?crls ?allowed_hashes ~time ta 289 + 290 + let certificate kv = 291 + let read name = 292 + read kv (Mirage_kv.Key.v (name ^ ".pem")) >|= Cstruct.to_string >>= 293 + decode_or_fail X509.Certificate.decode_pem_multiple >>= fun certs -> 294 + read kv (Mirage_kv.Key.v (name ^ ".key")) >|= Cstruct.to_string >>= 295 + decode_or_fail X509.Private_key.decode_pem >|= fun pk -> 296 + (certs, pk) 297 + in function | `Default -> read default_cert 298 + | `Name name -> read name 299 + end
+70
vendor/opam/tls/mirage/tls_mirage.mli
··· 1 + (** Effectful operations using Mirage for pure TLS. *) 2 + 3 + (** TLS module given a flow *) 4 + module Make (F : Mirage_flow.S) : sig 5 + 6 + (** possible errors: incoming alert, processing failure, or a 7 + problem in the underlying flow. *) 8 + type error = [ `Tls_alert of Tls.Packet.alert_type 9 + | `Tls_failure of Tls.Engine.failure 10 + | `Read of F.error 11 + | `Write of F.write_error ] 12 + 13 + type write_error = [ `Closed | error ] 14 + (** The type for write errors. *) 15 + 16 + (** we provide the FLOW interface *) 17 + include Mirage_flow.S 18 + with type error := error 19 + and type write_error := write_error 20 + 21 + (** [underlying t] returns the underlying flow. This is useful to extract 22 + information such as [src] and [dst] of that flow. *) 23 + val underlying : flow -> F.flow 24 + 25 + (** [reneg ~authenticator ~acceptable_cas ~cert ~drop t] renegotiates the 26 + session, and blocks until the renegotiation finished. Optionally, a new 27 + [authenticator] and [acceptable_cas] can be used. The own certificate can 28 + be adjusted by [cert]. If [drop] is [true] (the default), 29 + application data received before the renegotiation finished is dropped. *) 30 + val reneg : ?authenticator:X509.Authenticator.t -> 31 + ?acceptable_cas:X509.Distinguished_name.t list -> ?cert:Tls.Config.own_cert -> 32 + ?drop:bool -> flow -> (unit, [ write_error | `Msg of string ]) result Lwt.t 33 + 34 + (** [key_update ~request t] updates the traffic key and requests a traffic key 35 + update from the peer if [request] is provided and [true] (the default). 36 + This is only supported in TLS 1.3. *) 37 + val key_update : ?request:bool -> flow -> (unit, [ write_error | `Msg of string ]) result Lwt.t 38 + 39 + (** [client_of_flow client ~host flow] upgrades the existing connection 40 + to TLS using the [client] configuration, using [host] as peer name. *) 41 + val client_of_flow : Tls.Config.client -> ?host:[ `host ] Domain_name.t -> 42 + F.flow -> (flow, write_error) result Lwt.t 43 + 44 + (** [server_of_flow server flow] upgrades the flow to a TLS 45 + connection using the [server] configuration. *) 46 + val server_of_flow : Tls.Config.server -> F.flow -> 47 + (flow, write_error) result Lwt.t 48 + 49 + (** [epoch flow] extracts information of the established session. *) 50 + val epoch : flow -> (Tls.Core.epoch_data, unit) result 51 + 52 + end 53 + 54 + (** X.509 handling given a key value store and a clock *) 55 + module X509 (KV : Mirage_kv.RO) : sig 56 + (** [authenticator ~allowed_hashes ~crl store] creates an [authenticator], 57 + using the given certificate authorities in the [store] as 58 + value for key "ca_roots.crt". If [allowed_hashes] is provided, 59 + only these hash algorithms are allowed for signatures of the certificate chain. 60 + If [crl] is provided, the corresponding file is read and used as 61 + revocation list (DER encoded). Both options only apply if [`CAs] is used. 62 + *) 63 + val authenticator : ?allowed_hashes:Digestif.hash' list -> ?crl:string -> 64 + KV.t -> X509.Authenticator.t Lwt.t 65 + 66 + (** [certificate store typ] unmarshals a certificate chain and 67 + private key material from the [store]. *) 68 + val certificate : KV.t -> [< `Default | `Name of string ] 69 + -> Tls.Config.certchain Lwt.t 70 + end
+61
vendor/opam/tls/sni.md
··· 1 + ### Server Name Indication 2 + 3 + Some TLS servers might want to provide service for various services, 4 + all on the same port, but with different names. The SNI extension 5 + allows a client to request a specific server name. The server may use 6 + the requested server name to select the X.509 certificate chain which 7 + it presents to the client. 8 + 9 + ### Configuration interface 10 + 11 + A user provides a full certificate chain and a private key 12 + corresponding to the first certificate in the list to OCaml-TLS, 13 + captured by the type `certchain`. 14 + 15 + ```` 16 + type certchain = Certificate.certificate list * Nocrypto.Rsa.priv 17 + ```` 18 + 19 + The `own_cert` polymorphic variant covers the various configuration 20 + options: either no certificate is provided, a single one, multiple 21 + ones (whose common name/subject alternative name are used for 22 + disambiguation), and multiple with a default one. 23 + 24 + ```` 25 + type own_cert = [ 26 + | `None 27 + | `Single of certchain 28 + | `Multiple of certchain list 29 + | `Multiple_default of certchain * certchain list 30 + ] 31 + 32 + ```` 33 + 34 + ### Validation 35 + 36 + The configuration of certificates is intertwined with ciphersuites: 37 + each ciphersuite which requires a certificate furthermore depends on 38 + properties of this certificate - RSA and DHE_RSA require the key to be 39 + RSA, RSA requires the X.509v3 extension key_usage to contain 40 + encipherment, DHE_RSA requires key_usage to contain digital_signature. 41 + There must exist at least one certificate with the mentioned 42 + properties for each configured ciphersuite. 43 + 44 + Furthermore, to avoid ambiguity, the hostnames in ``Multiple` and 45 + ``Multiple_default` certificate lists must be non-overlapping. 46 + 47 + ### Certificate selection 48 + 49 + If the server is configured with only a default certificate, this is 50 + always used. 51 + 52 + If the client does not request for a server name, the default 53 + certificate is used. 54 + 55 + If the client requests a specific server name: 56 + - find a strict match 57 + - find a wildcard match 58 + - use the default one if present 59 + 60 + Only after a certificate is set for the session, the ciphersuite is 61 + selected, depending on the properties of the certificate.
+6
vendor/opam/tls/tests/dh.pem
··· 1 + -----BEGIN DH PARAMETERS----- 2 + MIGHAoGBAPmqFdDJzIT7OkV3ilTUbNK/vi8uosLWRg6BPoS3JdyUYchJgrXTX1wn 3 + YDOMD64s+5mONvFY4qOMBvdHgWYsppunnZT4UN18QkZeLuWslu12RiDUbI7HY5vY 4 + 0NX2NvKfBXVp0lChvM1v9s7N14ID3t7cXlfwu3IaAcs3jgc2ZR9TAgEC 5 + -----END DH PARAMETERS----- 6 +
+24
vendor/opam/tls/tests/dune
··· 1 + (library 2 + (name testlib) 3 + (modules testlib) 4 + (libraries tls ounit2 mirage-crypto-rng.unix) 5 + (optional)) 6 + 7 + (test 8 + (name unittestrunner) 9 + (package tls) 10 + (modules readertests readerwritertests writertests unittests unittestrunner) 11 + (libraries tls ounit2 testlib)) 12 + 13 + (test 14 + (name key_derivation) 15 + (package tls) 16 + (modules key_derivation) 17 + (libraries tls mirage-crypto-rng.unix alcotest logs.fmt)) 18 + 19 + (test 20 + (name feedback) 21 + (package tls) 22 + (modules feedback) 23 + (deps server.key server.pem) 24 + (libraries tls x509 testlib cmdliner fmt.cli logs.fmt fmt.tty logs.cli))
+134
vendor/opam/tls/tests/feedback.ml
··· 1 + 2 + module Flow = struct 3 + 4 + let rewrap_st = function (`S _, st) -> `S st | (`C _, st) -> `C st 5 + 6 + let unwrap_st = function `S st -> st | `C st -> st 7 + 8 + let can_handle_appdata st = 9 + not (Tls.Engine.handshake_in_progress (unwrap_st st)) 10 + 11 + let send_application_data state data = 12 + match Tls.Engine.send_application_data (unwrap_st state) data with 13 + | None -> None 14 + | Some (st', cs) -> Some (rewrap_st (state, st'), cs) 15 + 16 + let handle_tls ~tag state msg = 17 + let (st, descr) = match state with 18 + | `S st -> (st, "server") 19 + | `C st -> (st, "client") 20 + in 21 + match msg with 22 + | None -> state, None, None 23 + | Some msg -> 24 + match Tls.Engine.handle_tls st msg with 25 + | Ok (_, Some `Eof, _, _) -> 26 + failwith "received eof" 27 + | Ok (st', _eof, `Response (Some ans), `Data appdata) -> 28 + (rewrap_st (state, st'), Some ans, appdata) 29 + | Ok (st', _eof, `Response None, `Data appdata) -> 30 + (rewrap_st (state, st'), None, appdata) 31 + | Error (a, _) -> 32 + failwith @@ Printf.sprintf "[%s] %s error: %s" 33 + tag descr (Tls.Engine.string_of_failure a) 34 + end 35 + 36 + let get_ok = function 37 + | Ok cfg -> cfg 38 + | Error `Msg msg -> invalid_arg msg 39 + 40 + let loop_chatter ~certificate ~loops ~size = 41 + 42 + Printf.eprintf "Looping %d times, %d bytes.\n%!" loops size; 43 + 44 + let message = Mirage_crypto_rng.generate size 45 + and server = Tls.(Engine.server (get_ok (Config.server ~certificates:(`Single certificate) ()))) 46 + and (client, init) = 47 + let authenticator ?ip:_ ~host:_ _ = Ok None in 48 + Tls.(Engine.client @@ get_ok (Config.client ~authenticator ())) 49 + in 50 + Testlib.time @@ fun () -> 51 + 52 + let rec handshake srv cli cli_msg = 53 + let tag = "handshake" in 54 + let (srv, ans, _) = Flow.handle_tls ~tag srv cli_msg in 55 + let (cli, ans, _) = Flow.handle_tls ~tag cli ans in 56 + if Flow.can_handle_appdata cli && Flow.can_handle_appdata srv then (srv, cli) else 57 + handshake srv cli ans 58 + 59 + and chat srv cli data = function 60 + | 0 -> data 61 + | n -> 62 + let tag = "chat" in 63 + let simplex sender recv data = 64 + match Flow.send_application_data sender [data] with 65 + | None -> failwith @@ "can't send" 66 + | Some (sender', msg) -> 67 + match Flow.handle_tls ~tag recv (Some msg) with 68 + | (recv', _, Some data') -> (sender', recv', data') 69 + | (_, _, None) -> failwith "expected data" 70 + in 71 + let (cli, srv, data1) = simplex cli srv data in 72 + let (srv, cli, data2) = simplex srv cli data1 in 73 + chat srv cli data2 (pred n) 74 + in 75 + let (srv, cli) = handshake (`S server) (`C client) (Some init) in 76 + let message' = chat srv cli message loops in 77 + if String.equal message message' then Ok () 78 + else Error "the message got corrupted :(" 79 + 80 + let string_of_file file = 81 + try 82 + let fh = open_in file in 83 + let content = really_input_string fh (in_channel_length fh) in 84 + close_in_noerr fh; 85 + content 86 + with _ -> invalid_arg "Error reading file" 87 + 88 + let load_priv () = 89 + let cert, key = 90 + if Sys.file_exists "./certificates/server.pem" then 91 + "./certificates/server.pem", "./certificates/server.key" 92 + else 93 + "server.pem", "server.key" 94 + in 95 + let cs1 = string_of_file cert 96 + and cs2 = string_of_file key in 97 + match 98 + X509.Certificate.decode_pem_multiple cs1, X509.Private_key.decode_pem cs2 99 + with 100 + | Ok certs, Ok key -> certs, key 101 + | Error (`Msg m), _ -> failwith ("can't parse certificates " ^ m) 102 + | _, Error (`Msg m) -> failwith ("can't parse private key " ^ m) 103 + 104 + let jump () loops size = 105 + let certificate = load_priv () in 106 + loop_chatter ~certificate ~loops ~size 107 + 108 + let setup_log style_renderer level = 109 + Fmt_tty.setup_std_outputs ?style_renderer (); 110 + Logs.set_level level; 111 + Logs.set_reporter (Logs_fmt.reporter ~dst:Format.std_formatter ()) 112 + 113 + open Cmdliner 114 + 115 + let setup_log = 116 + Term.(const setup_log 117 + $ Fmt_cli.style_renderer () 118 + $ Logs_cli.level ()) 119 + 120 + let loops = 121 + let doc = "Number of loops to take" in 122 + Arg.(value & opt int 10 & info ~docv:"LOOPS" ~doc ["loops"]) 123 + 124 + let size = 125 + let doc = "Bytes to exchange" in 126 + Arg.(value & opt int 1024 & info ~docv:"SIZE" ~doc ["size"]) 127 + 128 + let cmd = 129 + let term = Term.(const jump $ setup_log $ loops $ size) 130 + and info = Cmd.info "feedback" ~version:"%%VERSION_NUM%%" 131 + in 132 + Cmd.v info term 133 + 134 + let () = exit (Cmd.eval_result cmd)
+89
vendor/opam/tls/tests/interop-mbedtls-client2.sh
··· 1 + #!/bin/sh 2 + 3 + port=4455 4 + polarssl="/opt/bin/mbedtls_ssl_client2 auth_mode=none server_port=" 5 + 6 + extra_args="" 7 + statfile="/tmp/test_server.status" 8 + 9 + testit () { 10 + /bin/sh -c "cd .. && ./_build/default/lwt/examples/test_server.exe $port > /dev/null && echo foo > $statfile" & 11 + 12 + sleep 0.3 13 + 14 + $polarssl$port $extra_args 2> /dev/null > /dev/null 15 + 16 + sleep 0.3 17 + 18 + if [ -e $statfile ]; then 19 + result=$(cat $statfile) 20 + if [ $result = "foo" ]; then 21 + echo "success with $extra_args" 22 + else 23 + echo "failure with $polarssl$port $extra_args (statfile there)" 24 + exit 1 25 + fi 26 + rm $statfile 27 + else 28 + echo "failure with $polarssl$port $extra_args" 29 + exit 1 30 + fi 31 + sleep 0.3 32 + port=$(expr $port + 1) 33 + } 34 + 35 + testit 36 + 37 + extra_args="force_version=tls1" 38 + testit 39 + 40 + extra_args="force_version=tls1_1" 41 + testit 42 + 43 + extra_args="force_version=tls1_2" 44 + testit 45 + 46 + ciphers=" 47 + TLS-DHE-RSA-WITH-AES-256-CBC-SHA 48 + TLS-DHE-RSA-WITH-AES-128-CBC-SHA 49 + TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA 50 + TLS-RSA-WITH-AES-256-CBC-SHA 51 + TLS-RSA-WITH-AES-128-CBC-SHA 52 + TLS-RSA-WITH-3DES-EDE-CBC-SHA 53 + TLS-RSA-WITH-RC4-128-SHA 54 + TLS-RSA-WITH-RC4-128-MD5" 55 + 56 + for i in $ciphers; do 57 + extra_args="force_ciphersuite=$i" 58 + testit 59 + 60 + extra_args="force_version=tls1 force_ciphersuite=$i" 61 + testit 62 + 63 + extra_args="force_version=tls1_1 force_ciphersuite=$i" 64 + testit 65 + 66 + extra_args="force_version=tls1_2 force_ciphersuite=$i" 67 + testit 68 + done 69 + 70 + tls12_ciphers=" 71 + TLS-DHE-RSA-WITH-AES-256-CCM 72 + TLS-DHE-RSA-WITH-AES-128-CCM 73 + TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 74 + TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 75 + TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 76 + TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 77 + TLS-RSA-WITH-AES-256-CCM 78 + TLS-RSA-WITH-AES-128-CCM 79 + TLS-RSA-WITH-AES-256-CBC-SHA256 80 + TLS-RSA-WITH-AES-128-CBC-SHA256 81 + TLS-RSA-WITH-AES-256-GCM-SHA384 82 + TLS-RSA-WITH-AES-128-GCM-SHA256" 83 + for i in $tls12_ciphers; do 84 + extra_args="force_ciphersuite=$i" 85 + testit 86 + 87 + extra_args="force_version=tls1_2 force_ciphersuite=$i" 88 + testit 89 + done
+82
vendor/opam/tls/tests/interop-openssl-sclient.sh
··· 1 + #!/bin/sh 2 + 3 + port=4455 4 + s_client_args="s_client -quiet -connect 127.0.0.1:" 5 + 6 + extra_args="" 7 + statfile="/tmp/test_server.status" 8 + 9 + testit () { 10 + /bin/sh -c "cd ../ && ./_build/default/lwt/examples/test_server.exe $port > /dev/null && echo foo > $statfile" & 11 + 12 + sleep 0.3 13 + 14 + echo "GET /" | openssl $s_client_args$port $extra_args 2> /dev/null > /dev/null 15 + 16 + sleep 0.3 17 + 18 + if [ -e $statfile ]; then 19 + result=$(cat $statfile) 20 + if [ $result = "foo" ]; then 21 + echo "success with $extra_args" 22 + else 23 + echo "failure with openssl $s_client_args $extra_args (statfile there)" 24 + exit 1 25 + fi 26 + rm $statfile 27 + else 28 + echo "failure with openssl $s_client_args$port $extra_args (no statfile)" 29 + exit 1 30 + fi 31 + sleep 0.3 32 + port=$(expr $port + 1) 33 + } 34 + 35 + testit 36 + 37 + extra_args="-tls1" 38 + testit 39 + 40 + extra_args="-tls1_1" 41 + testit 42 + 43 + extra_args="-tls1_2" 44 + testit 45 + 46 + extra_args="-tls1_3" 47 + testit 48 + 49 + ciphers="DHE-RSA-AES256-SHA AES256-SHA DHE-RSA-AES128-SHA AES128-SHA ECDHE-RSA-AES256-SHA ECDHE-RSA-AES128-SHA ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA" 50 + #OpenSSL <1.1.1: 51 + #EDH-RSA-DES-CBC3-SHA DES-CBC3-SHA 52 + for i in $ciphers; do 53 + extra_args="-cipher $i" 54 + testit 55 + 56 + extra_args="-tls1 -cipher $i" 57 + testit 58 + 59 + extra_args="-tls1_1 -cipher $i" 60 + testit 61 + 62 + extra_args="-tls1_2 -cipher $i" 63 + testit 64 + done 65 + 66 + tls12_ciphers="DHE-RSA-AES256-SHA256 AES256-SHA256 DHE-RSA-AES128-SHA256 AES128-SHA256 AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-SHA384 ECDHE-RSA-AES128-SHA256 ECDHE-RSA-CHACHA20-POLY1305 DHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-CHACHA20-POLY1305" 67 + for i in $tls12_ciphers; do 68 + extra_args="-cipher $i" 69 + testit 70 + 71 + extra_args="-tls1_2 -cipher $i" 72 + testit 73 + done 74 + 75 + tls13_ciphers="TLS_AES_256_GCM_SHA384 TLS_AES_128_GCM_SHA256 TLS_CHACHA20_POLY1305_SHA256" 76 + for i in $tls13_ciphers; do 77 + extra_args="-ciphersuites $i" 78 + testit 79 + 80 + extra_args="-tls1_3 -ciphersuites $i" 81 + testit 82 + done
+124
vendor/opam/tls/tests/interop-openssl-sserver.sh
··· 1 + #!/bin/sh 2 + 3 + s_server_args="s_server -quiet -key ../certificates/server.key -cert ../certificates/server.pem -www -dhparam dh.pem " 4 + 5 + pidfile='/tmp/openssl.pid' 6 + 7 + extra_args="" 8 + 9 + testit () { 10 + /bin/sh -c "echo \$\$ > $pidfile && exec openssl $s_server_args $extra_args" & 11 + 12 + sleep 0.3 13 + 14 + ../_build/default/lwt/examples/test_client.exe > /dev/null 15 + 16 + if [ $? -eq 0 ]; then 17 + echo "success with $extra_args" 18 + else 19 + echo "failure with openssl $s_server_args $extra_args" 20 + exit 1 21 + fi 22 + cat $pidfile | xargs kill 23 + rm $pidfile 24 + sleep 0.5 25 + } 26 + 27 + testit 28 + 29 + extra_args="-tls1" 30 + testit 31 + 32 + extra_args="-tls1_1" 33 + testit 34 + 35 + extra_args="-tls1_2" 36 + testit 37 + 38 + extra_args="-tls1_3" 39 + testit 40 + 41 + ciphers="DHE-RSA-AES256-SHA AES256-SHA DHE-RSA-AES128-SHA AES128-SHA ECDHE-RSA-AES256-SHA ECDHE-RSA-AES128-SHA" 42 + #OpenSSL <1.1.1: 43 + #EDH-RSA-DES-CBC3-SHA DES-CBC3-SHA 44 + for i in $ciphers; do 45 + extra_args="-cipher $i" 46 + testit 47 + 48 + extra_args="-tls1 -cipher $i" 49 + testit 50 + 51 + extra_args="-tls1_1 -cipher $i" 52 + testit 53 + 54 + extra_args="-tls1_2 -cipher $i" 55 + testit 56 + done 57 + 58 + tls12_ciphers="DHE-RSA-AES256-SHA256 AES256-SHA256 DHE-RSA-AES128-SHA256 AES128-SHA256 AES128-GCM-SHA256 DHE-RSA-AES128-GCM-SHA256 AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-SHA384 ECDHE-RSA-AES128-SHA256 ECDHE-RSA-CHACHA20-POLY1305 DHE-RSA-CHACHA20-POLY1305" 59 + for i in $tls12_ciphers; do 60 + extra_args="-cipher $i" 61 + testit 62 + 63 + extra_args="-tls1_2 -cipher $i" 64 + testit 65 + done 66 + 67 + tls13_ciphers="TLS_AES_256_GCM_SHA384 TLS_AES_128_GCM_SHA256 TLS_CHACHA20_POLY1305_SHA256" 68 + for i in $tls13_ciphers; do 69 + extra_args="-ciphersuites $i" 70 + testit 71 + 72 + extra_args="-tls1_3 -ciphersuites $i" 73 + testit 74 + done 75 + 76 + s_server_args="s_server -quiet -key ../certificates/server-ec.key -cert ../certificates/server-ec.pem -www -dhparam dh.pem " 77 + ec_ciphers="ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA" 78 + ec_ciphers12="ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-CHACHA20-POLY1305" 79 + 80 + extra_args="" 81 + testit 82 + 83 + extra_args="-tls1" 84 + testit 85 + 86 + extra_args="-tls1_1" 87 + testit 88 + 89 + extra_args="-tls1_2" 90 + testit 91 + 92 + extra_args="-tls1_3" 93 + testit 94 + 95 + for i in $ec_ciphers; do 96 + extra_args="-cipher $i" 97 + testit 98 + 99 + extra_args="-tls1 -cipher $i" 100 + testit 101 + 102 + extra_args="-tls1_1 -cipher $i" 103 + testit 104 + 105 + extra_args="-tls1_2 -cipher $i" 106 + testit 107 + done 108 + 109 + for i in $ec_ciphers12; do 110 + extra_args="-cipher $i" 111 + testit 112 + 113 + extra_args="-tls1_2 -cipher $i" 114 + testit 115 + done 116 + 117 + tls13_ciphers="TLS_AES_256_GCM_SHA384 TLS_AES_128_GCM_SHA256 TLS_CHACHA20_POLY1305_SHA256" 118 + for i in $tls13_ciphers; do 119 + extra_args="-ciphersuites $i" 120 + testit 121 + 122 + extra_args="-tls1_3 -ciphersuites $i" 123 + testit 124 + done
+697
vendor/opam/tls/tests/key_derivation.ml
··· 1 + (* key derivation example trace taken from draft-ietf-tls-tls13-vectors-07 *) 2 + let cs = 3 + let module M = struct 4 + type t = string 5 + let pp = Ohex.pp_hexdump () 6 + let equal = String.equal 7 + end in (module M : Alcotest.TESTABLE with type t = M.t) 8 + 9 + let secret0 = Ohex.decode {| 10 + 33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c e2 11 + 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a 12 + |} 13 + 14 + let cipher = `AES_128_GCM_SHA256 15 + let hash = Tls.Ciphersuite.hash13 cipher 16 + 17 + let my_secret = ref None 18 + 19 + let extract_secret_early () = 20 + (* draft-ietf-tls-tls13-vectors-07 Sec 3*) 21 + let salt = "" 22 + and ikm = String.make 32 '\x00' 23 + in 24 + Alcotest.check cs __LOC__ secret0 (Hkdf.extract ~hash ~salt ikm) ; 25 + let t = Tls.Handshake_crypto13.(derive (empty cipher) ikm) in 26 + my_secret := Some t ; 27 + Alcotest.check cs __LOC__ secret0 t.secret 28 + 29 + let expand0 = Ohex.decode {| 30 + 6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba b6 97 31 + 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba 32 + |} 33 + 34 + let derive_hs_secret () = 35 + let module H = (val Digestif.module_of_hash' hash) in 36 + let hash_val = H.(to_raw_string (digest_string "")) in 37 + Alcotest.check cs __LOC__ expand0 38 + (Tls.Handshake_crypto13.derive_secret_no_hash hash secret0 ~ctx:hash_val "derived") 39 + 40 + let hs_secret = Ohex.decode {| 41 + 1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01 42 + 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac 43 + |} 44 + 45 + (* TODO: ikm should be computed (ECDHE) from the key share in client hello (see 46 + below), and the private key written in the RFC. *) 47 + let ikm = Ohex.decode {| 48 + 8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d 49 + 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d 50 + |} 51 + 52 + let extract_handshake () = 53 + Alcotest.check cs __LOC__ hs_secret (Hkdf.extract ~hash ~salt:expand0 ikm) ; 54 + match !my_secret with 55 + | None -> Alcotest.fail "expected some secret" 56 + | Some t -> 57 + let t' = Tls.Handshake_crypto13.derive t ikm in 58 + my_secret := Some t' ; 59 + Alcotest.check cs __LOC__ hs_secret t'.secret 60 + 61 + let ch = Ohex.decode {| 62 + 01 00 00 c0 03 03 cb 34 ec b1 e7 81 63 ba 1c 38 63 + c6 da cb 19 6a 6d ff a2 1a 8d 99 12 ec 18 a2 ef 64 + 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 65 + 00 00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 66 + 65 72 ff 01 00 01 00 00 0a 00 14 00 12 00 1d 00 67 + 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 68 + 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d 69 + e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 70 + 51 c1 3c ae 4d 54 13 69 1e 52 9a af 2c 00 2b 00 71 + 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03 72 + 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 73 + 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 74 + 00 02 40 01 75 + |} 76 + 77 + let sh = Ohex.decode {| 78 + 02 00 00 56 03 03 a6 af 06 a4 12 18 60 dc 5e 6e 79 + 60 24 9c d3 4c 95 93 0c 8a c5 cb 14 34 da c1 55 80 + 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 81 + 00 1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db 82 + f7 c6 72 e1 56 d6 cc 25 3b 83 3d f1 dd 69 b1 b0 83 + 4e 75 1f 0f 00 2b 00 02 03 04 84 + |} 85 + 86 + let c_hs_traffic_secret = Ohex.decode {| 87 + b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e 2d 8f 88 + 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21 89 + |} 90 + 91 + let read_handshake_key = Ohex.decode {| 92 + db fa a6 93 d1 76 2c 5b 66 6a f5 d9 50 25 8d 01 93 + |} 94 + 95 + let read_handshake_iv = Ohex.decode {| 96 + 5b d3 c7 1b 83 6e 0b 76 bb 73 26 5f 97 + |} 98 + 99 + let derive_c_hs_traffic () = 100 + let log = ch ^ sh in 101 + let hash_val = 102 + let module H = (val Digestif.module_of_hash' hash) in 103 + H.(to_raw_string (digest_string log)) 104 + in 105 + Alcotest.check cs __LOC__ c_hs_traffic_secret 106 + (Tls.Handshake_crypto13.derive_secret_no_hash hash hs_secret ~ctx:hash_val "c hs traffic") ; 107 + match !my_secret with 108 + | None -> Alcotest.fail "expected my secret" 109 + | Some t -> 110 + let c_hs_traffic = Tls.Handshake_crypto13.derive_secret t "c hs traffic" log in 111 + Alcotest.check cs __LOC__ c_hs_traffic_secret c_hs_traffic ; 112 + let key, iv = Tls.Handshake_crypto13.traffic_key cipher c_hs_traffic in 113 + Alcotest.check cs __LOC__ read_handshake_key key ; 114 + Alcotest.check cs __LOC__ read_handshake_iv iv 115 + 116 + let derive_read_handshake_keys () = 117 + Alcotest.check cs __LOC__ read_handshake_key 118 + (Tls.Handshake_crypto13.derive_secret_no_hash hash c_hs_traffic_secret ~length:16 "key") ; 119 + Alcotest.check cs __LOC__ read_handshake_iv 120 + (Tls.Handshake_crypto13.derive_secret_no_hash hash c_hs_traffic_secret ~length:12 "iv") 121 + 122 + let s_hs_traffic_secret = Ohex.decode {| 123 + b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4 124 + e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38 125 + |} 126 + 127 + let write_handshake_key = Ohex.decode {| 128 + 3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e e4 03 bc 129 + |} 130 + 131 + let write_handshake_iv = Ohex.decode {| 132 + 5d 31 3e b2 67 12 76 ee 13 00 0b 30 133 + |} 134 + 135 + let derive_s_hs_traffic () = 136 + let log = ch ^ sh in 137 + let hash_val = 138 + let module H = (val Digestif.module_of_hash' hash) in 139 + H.(to_raw_string (digest_string log)) 140 + in 141 + Alcotest.check cs __LOC__ s_hs_traffic_secret 142 + (Tls.Handshake_crypto13.derive_secret_no_hash hash hs_secret ~ctx:hash_val "s hs traffic") ; 143 + match !my_secret with 144 + | None -> Alcotest.fail "expected my secret" 145 + | Some t -> 146 + let s_hs_traffic = Tls.Handshake_crypto13.derive_secret t "s hs traffic" log in 147 + Alcotest.check cs __LOC__ s_hs_traffic_secret s_hs_traffic ; 148 + let key, iv = Tls.Handshake_crypto13.traffic_key cipher s_hs_traffic in 149 + Alcotest.check cs __LOC__ write_handshake_key key ; 150 + Alcotest.check cs __LOC__ write_handshake_iv iv 151 + 152 + let derive_write_handshake_keys () = 153 + Alcotest.check cs __LOC__ write_handshake_key 154 + (Tls.Handshake_crypto13.derive_secret_no_hash hash s_hs_traffic_secret ~length:16 "key") ; 155 + Alcotest.check cs __LOC__ write_handshake_iv 156 + (Tls.Handshake_crypto13.derive_secret_no_hash hash s_hs_traffic_secret ~length:12"iv") 157 + 158 + let finished_expanded = Ohex.decode {| 159 + 00 8d 3b 66 f8 16 ea 55 9f 96 b5 37 e8 85 c3 1f 160 + c0 68 bf 49 2c 65 2f 01 f2 88 a1 d8 cd c1 9f c8 161 + |} 162 + 163 + let finished_key = Ohex.decode {| 164 + 9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4 de da 165 + 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18 166 + |} 167 + 168 + let enc_ext = Ohex.decode {| 169 + 08 00 00 24 00 22 00 0a 00 14 00 12 00 1d 00 17 170 + 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c 171 + 00 02 40 01 00 00 00 00 172 + |} 173 + 174 + let cert = Ohex.decode {| 175 + 0b 00 01 b9 00 00 01 b5 00 01 b0 30 82 01 ac 30 176 + 82 01 15 a0 03 02 01 02 02 01 02 30 0d 06 09 2a 177 + 86 48 86 f7 0d 01 01 0b 05 00 30 0e 31 0c 30 0a 178 + 06 03 55 04 03 13 03 72 73 61 30 1e 17 0d 31 36 179 + 30 37 33 30 30 31 32 33 35 39 5a 17 0d 32 36 30 180 + 37 33 30 30 31 32 33 35 39 5a 30 0e 31 0c 30 0a 181 + 06 03 55 04 03 13 03 72 73 61 30 81 9f 30 0d 06 182 + 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 183 + 30 81 89 02 81 81 00 b4 bb 49 8f 82 79 30 3d 98 184 + 08 36 39 9b 36 c6 98 8c 0c 68 de 55 e1 bd b8 26 185 + d3 90 1a 24 61 ea fd 2d e4 9a 91 d0 15 ab bc 9a 186 + 95 13 7a ce 6c 1a f1 9e aa 6a f9 8c 7c ed 43 12 187 + 09 98 e1 87 a8 0e e0 cc b0 52 4b 1b 01 8c 3e 0b 188 + 63 26 4d 44 9a 6d 38 e2 2a 5f da 43 08 46 74 80 189 + 30 53 0e f0 46 1c 8c a9 d9 ef bf ae 8e a6 d1 d0 190 + 3e 2b d1 93 ef f0 ab 9a 80 02 c4 74 28 a6 d3 5a 191 + 8d 88 d7 9f 7f 1e 3f 02 03 01 00 01 a3 1a 30 18 192 + 30 09 06 03 55 1d 13 04 02 30 00 30 0b 06 03 55 193 + 1d 0f 04 04 03 02 05 a0 30 0d 06 09 2a 86 48 86 194 + f7 0d 01 01 0b 05 00 03 81 81 00 85 aa d2 a0 e5 195 + b9 27 6b 90 8c 65 f7 3a 72 67 17 06 18 a5 4c 5f 196 + 8a 7b 33 7d 2d f7 a5 94 36 54 17 f2 ea e8 f8 a5 197 + 8c 8f 81 72 f9 31 9c f3 6b 7f d6 c5 5b 80 f2 1a 198 + 03 01 51 56 72 60 96 fd 33 5e 5e 67 f2 db f1 02 199 + 70 2e 60 8c ca e6 be c1 fc 63 a4 2a 99 be 5c 3e 200 + b7 10 7c 3c 54 e9 b9 eb 2b d5 20 3b 1c 3b 84 e0 201 + a8 b2 f7 59 40 9b a3 ea c9 d9 1d 40 2d cc 0c c8 202 + f8 96 12 29 ac 91 87 b4 2b 4d e1 00 00 203 + |} 204 + 205 + let cert_verify = Ohex.decode {| 206 + 0f 00 00 84 08 04 00 80 5a 74 7c 5d 88 fa 9b d2 207 + e5 5a b0 85 a6 10 15 b7 21 1f 82 4c d4 84 14 5a 208 + b3 ff 52 f1 fd a8 47 7b 0b 7a bc 90 db 78 e2 d3 209 + 3a 5c 14 1a 07 86 53 fa 6b ef 78 0c 5e a2 48 ee 210 + aa a7 85 c4 f3 94 ca b6 d3 0b be 8d 48 59 ee 51 211 + 1f 60 29 57 b1 54 11 ac 02 76 71 45 9e 46 44 5c 212 + 9e a5 8c 18 1e 81 8e 95 b8 c3 fb 0b f3 27 84 09 213 + d3 be 15 2a 3d a5 04 3e 06 3d da 65 cd f5 ae a2 214 + 0d 53 df ac d4 2f 74 f3 215 + |} 216 + 217 + let derive_finished () = 218 + let log = String.concat "" [ ch ; sh ; enc_ext ; cert ; cert_verify ] in 219 + Alcotest.check cs __LOC__ finished_expanded 220 + (Tls.Handshake_crypto13.derive_secret_no_hash hash s_hs_traffic_secret "finished") ; 221 + let module H = (val Digestif.module_of_hash' hash) in 222 + let hash_val = H.(to_raw_string (digest_string log)) in 223 + Alcotest.check cs __LOC__ finished_key 224 + H.(to_raw_string (hmac_string ~key:finished_expanded hash_val)) ; 225 + match !my_secret with 226 + | None -> Alcotest.fail "expected some secret" 227 + | Some t -> 228 + let s_hs_traffic = Tls.Handshake_crypto13.derive_secret t "s hs traffic" (ch ^ sh) in 229 + Alcotest.check cs __LOC__ s_hs_traffic_secret s_hs_traffic ; 230 + Alcotest.check cs __LOC__ finished_key 231 + (Tls.Handshake_crypto13.finished t.hash s_hs_traffic log) 232 + 233 + let finished = Ohex.decode {| 234 + 14 00 00 20 9b 9b 14 1d 90 63 37 fb d2 cb dc e7 235 + 1d f4 de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 236 + b7 8f 07 18 237 + |} 238 + 239 + let master = Ohex.decode {| 240 + 43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25 90 b5 241 + 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4 242 + |} 243 + 244 + let derive_master () = 245 + let module H = (val Digestif.module_of_hash' hash) in 246 + let hash_val = H.(to_raw_string (digest_string "")) in 247 + Alcotest.check cs __LOC__ master 248 + (Tls.Handshake_crypto13.derive_secret_no_hash hash hs_secret ~ctx:hash_val "derived") 249 + 250 + let master_secret = Ohex.decode {| 251 + 18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47 252 + 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19 253 + |} 254 + 255 + let extract_master () = 256 + Alcotest.check cs __LOC__ master_secret (Hkdf.extract ~hash ~salt:master (String.make 32 '\x00')) ; 257 + match !my_secret with 258 + | None -> Alcotest.fail "expected my secret" 259 + | Some t -> 260 + let t' = Tls.Handshake_crypto13.derive t (String.make 32 '\x00') in 261 + my_secret := Some t' ; 262 + Alcotest.check cs __LOC__ master_secret t'.secret 263 + 264 + let c_ap_traffic = Ohex.decode {| 265 + 9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce 65 52 266 + 87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5 267 + |} 268 + 269 + let s_ap_traffic = Ohex.decode {| 270 + a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9 50 32 271 + 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43 272 + |} 273 + 274 + let exp_master = Ohex.decode {| 275 + fe 22 f8 81 17 6e da 18 eb 8f 44 52 9e 67 92 c5 276 + 0c 9a 3f 89 45 2f 68 d8 ae 31 1b 43 09 d3 cf 50 277 + |} 278 + 279 + let app_write_key = Ohex.decode {| 280 + 9f 02 28 3b 6c 9c 07 ef c2 6b b9 f2 ac 92 e3 56 281 + |} 282 + 283 + let app_write_iv = Ohex.decode {| 284 + cf 78 2b 88 dd 83 54 9a ad f1 e9 84 285 + |} 286 + 287 + let app_read_key = Ohex.decode {| 288 + 17 42 2d da 59 6e d5 d9 ac d8 90 e3 c6 3f 50 51 289 + |} 290 + 291 + let app_read_iv = Ohex.decode {| 292 + 5b 78 92 3d ee 08 57 90 33 e5 23 d9 293 + |} 294 + 295 + let derive_traffic_keys () = 296 + let log = String.concat "" [ ch ; sh ; enc_ext ; cert ; cert_verify ; finished ] in 297 + let module H = (val Digestif.module_of_hash' hash) in 298 + let hash_val = H.(to_raw_string (digest_string log)) in 299 + Alcotest.check cs __LOC__ c_ap_traffic 300 + (Tls.Handshake_crypto13.derive_secret_no_hash hash master_secret ~ctx:hash_val "c ap traffic") ; 301 + Alcotest.check cs __LOC__ s_ap_traffic 302 + (Tls.Handshake_crypto13.derive_secret_no_hash hash master_secret ~ctx:hash_val "s ap traffic") ; 303 + Alcotest.check cs __LOC__ exp_master 304 + (Tls.Handshake_crypto13.derive_secret_no_hash hash master_secret ~ctx:hash_val "exp master") ; 305 + match !my_secret with 306 + | None -> Alcotest.fail "expected some secret" 307 + | Some t -> 308 + let c_ap_traffic' = Tls.Handshake_crypto13.derive_secret t "c ap traffic" log in 309 + Alcotest.check cs __LOC__ c_ap_traffic c_ap_traffic' ; 310 + let key, iv = Tls.Handshake_crypto13.traffic_key cipher c_ap_traffic' in 311 + Alcotest.check cs __LOC__ app_read_key key ; 312 + Alcotest.check cs __LOC__ app_read_iv iv ; 313 + let s_ap_traffic' = Tls.Handshake_crypto13.derive_secret t "s ap traffic" log in 314 + Alcotest.check cs __LOC__ s_ap_traffic s_ap_traffic' ; 315 + let key, iv = Tls.Handshake_crypto13.traffic_key cipher s_ap_traffic' in 316 + Alcotest.check cs __LOC__ app_write_key key ; 317 + Alcotest.check cs __LOC__ app_write_iv iv 318 + 319 + let appdata_write () = 320 + Alcotest.check cs __LOC__ app_write_key 321 + (Tls.Handshake_crypto13.derive_secret_no_hash hash s_ap_traffic ~length:16 "key") ; 322 + Alcotest.check cs __LOC__ app_write_iv 323 + (Tls.Handshake_crypto13.derive_secret_no_hash hash s_ap_traffic ~length:12 "iv") 324 + 325 + let appdata_read () = 326 + Alcotest.check cs __LOC__ app_read_key 327 + (Tls.Handshake_crypto13.derive_secret_no_hash hash c_ap_traffic ~length:16 "key") ; 328 + Alcotest.check cs __LOC__ app_read_iv 329 + (Tls.Handshake_crypto13.derive_secret_no_hash hash c_ap_traffic ~length:12 "iv") 330 + 331 + let server_payload = Ohex.decode {| 332 + 08 00 00 24 00 22 00 0a 00 14 00 12 00 1d 00 17 333 + 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c 334 + 00 02 40 01 00 00 00 00 0b 00 01 b9 00 00 01 b5 335 + 00 01 b0 30 82 01 ac 30 82 01 15 a0 03 02 01 02 336 + 02 01 02 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 337 + 05 00 30 0e 31 0c 30 0a 06 03 55 04 03 13 03 72 338 + 73 61 30 1e 17 0d 31 36 30 37 33 30 30 31 32 33 339 + 35 39 5a 17 0d 32 36 30 37 33 30 30 31 32 33 35 340 + 39 5a 30 0e 31 0c 30 0a 06 03 55 04 03 13 03 72 341 + 73 61 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 342 + 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 b4 343 + bb 49 8f 82 79 30 3d 98 08 36 39 9b 36 c6 98 8c 344 + 0c 68 de 55 e1 bd b8 26 d3 90 1a 24 61 ea fd 2d 345 + e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c 1a f1 9e 346 + aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 cc 347 + b0 52 4b 1b 01 8c 3e 0b 63 26 4d 44 9a 6d 38 e2 348 + 2a 5f da 43 08 46 74 80 30 53 0e f0 46 1c 8c a9 349 + d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93 ef f0 ab 9a 350 + 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 02 351 + 03 01 00 01 a3 1a 30 18 30 09 06 03 55 1d 13 04 352 + 02 30 00 30 0b 06 03 55 1d 0f 04 04 03 02 05 a0 353 + 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 354 + 81 81 00 85 aa d2 a0 e5 b9 27 6b 90 8c 65 f7 3a 355 + 72 67 17 06 18 a5 4c 5f 8a 7b 33 7d 2d f7 a5 94 356 + 36 54 17 f2 ea e8 f8 a5 8c 8f 81 72 f9 31 9c f3 357 + 6b 7f d6 c5 5b 80 f2 1a 03 01 51 56 72 60 96 fd 358 + 33 5e 5e 67 f2 db f1 02 70 2e 60 8c ca e6 be c1 359 + fc 63 a4 2a 99 be 5c 3e b7 10 7c 3c 54 e9 b9 eb 360 + 2b d5 20 3b 1c 3b 84 e0 a8 b2 f7 59 40 9b a3 ea 361 + c9 d9 1d 40 2d cc 0c c8 f8 96 12 29 ac 91 87 b4 362 + 2b 4d e1 00 00 0f 00 00 84 08 04 00 80 5a 74 7c 363 + 5d 88 fa 9b d2 e5 5a b0 85 a6 10 15 b7 21 1f 82 364 + 4c d4 84 14 5a b3 ff 52 f1 fd a8 47 7b 0b 7a bc 365 + 90 db 78 e2 d3 3a 5c 14 1a 07 86 53 fa 6b ef 78 366 + 0c 5e a2 48 ee aa a7 85 c4 f3 94 ca b6 d3 0b be 367 + 8d 48 59 ee 51 1f 60 29 57 b1 54 11 ac 02 76 71 368 + 45 9e 46 44 5c 9e a5 8c 18 1e 81 8e 95 b8 c3 fb 369 + 0b f3 27 84 09 d3 be 15 2a 3d a5 04 3e 06 3d da 370 + 65 cd f5 ae a2 0d 53 df ac d4 2f 74 f3 14 00 00 371 + 20 9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4 de 372 + da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 373 + 18 374 + |} 375 + 376 + let payload_is_good () = 377 + Alcotest.check cs __LOC__ server_payload 378 + (String.concat "" [ enc_ext ; cert ; cert_verify ; finished ]) 379 + 380 + let server_payload_processed = Ohex.decode {| 381 + 17 03 03 02 a2 d1 ff 33 4a 56 f5 bf f6 59 4a 07 382 + cc 87 b5 80 23 3f 50 0f 45 e4 89 e7 f3 3a f3 5e 383 + df 78 69 fc f4 0a a4 0a a2 b8 ea 73 f8 48 a7 ca 384 + 07 61 2e f9 f9 45 cb 96 0b 40 68 90 51 23 ea 78 385 + b1 11 b4 29 ba 91 91 cd 05 d2 a3 89 28 0f 52 61 386 + 34 aa dc 7f c7 8c 4b 72 9d f8 28 b5 ec f7 b1 3b 387 + d9 ae fb 0e 57 f2 71 58 5b 8e a9 bb 35 5c 7c 79 388 + 02 07 16 cf b9 b1 18 3e f3 ab 20 e3 7d 57 a6 b9 389 + d7 47 76 09 ae e6 e1 22 a4 cf 51 42 73 25 25 0c 390 + 7d 0e 50 92 89 44 4c 9b 3a 64 8f 1d 71 03 5d 2e 391 + d6 5b 0e 3c dd 0c ba e8 bf 2d 0b 22 78 12 cb b3 392 + 60 98 72 55 cc 74 41 10 c4 53 ba a4 fc d6 10 92 393 + 8d 80 98 10 e4 b7 ed 1a 8f d9 91 f0 6a a6 24 82 394 + 04 79 7e 36 a6 a7 3b 70 a2 55 9c 09 ea d6 86 94 395 + 5b a2 46 ab 66 e5 ed d8 04 4b 4c 6d e3 fc f2 a8 396 + 94 41 ac 66 27 2f d8 fb 33 0e f8 19 05 79 b3 68 397 + 45 96 c9 60 bd 59 6e ea 52 0a 56 a8 d6 50 f5 63 398 + aa d2 74 09 96 0d ca 63 d3 e6 88 61 1e a5 e2 2f 399 + 44 15 cf 95 38 d5 1a 20 0c 27 03 42 72 96 8a 26 400 + 4e d6 54 0c 84 83 8d 89 f7 2c 24 46 1a ad 6d 26 401 + f5 9e ca ba 9a cb bb 31 7b 66 d9 02 f4 f2 92 a3 402 + 6a c1 b6 39 c6 37 ce 34 31 17 b6 59 62 22 45 31 403 + 7b 49 ee da 0c 62 58 f1 00 d7 d9 61 ff b1 38 64 404 + 7e 92 ea 33 0f ae ea 6d fa 31 c7 a8 4d c3 bd 7e 405 + 1b 7a 6c 71 78 af 36 87 90 18 e3 f2 52 10 7f 24 406 + 3d 24 3d c7 33 9d 56 84 c8 b0 37 8b f3 02 44 da 407 + 8c 87 c8 43 f5 e5 6e b4 c5 e8 28 0a 2b 48 05 2c 408 + f9 3b 16 49 9a 66 db 7c ca 71 e4 59 94 26 f7 d4 409 + 61 e6 6f 99 88 2b d8 9f c5 08 00 be cc a6 2d 6c 410 + 74 11 6d bd 29 72 fd a1 fa 80 f8 5d f8 81 ed be 411 + 5a 37 66 89 36 b3 35 58 3b 59 91 86 dc 5c 69 18 412 + a3 96 fa 48 a1 81 d6 b6 fa 4f 9d 62 d5 13 af bb 413 + 99 2f 2b 99 2f 67 f8 af e6 7f 76 91 3f a3 88 cb 414 + 56 30 c8 ca 01 e0 c6 5d 11 c6 6a 1e 2a c4 c8 59 415 + 77 b7 c7 a6 99 9b bf 10 dc 35 ae 69 f5 51 56 14 416 + 63 6c 0b 9b 68 c1 9e d2 e3 1c 0b 3b 66 76 30 38 417 + eb ba 42 f3 b3 8e dc 03 99 f3 a9 f2 3f aa 63 97 418 + 8c 31 7f c9 fa 66 a7 3f 60 f0 50 4d e9 3b 5b 84 419 + 5e 27 55 92 c1 23 35 ee 34 0b bc 4f dd d5 02 78 420 + 40 16 e4 b3 be 7e f0 4d da 49 f4 b4 40 a3 0c b5 421 + d2 af 93 98 28 fd 4a e3 79 4e 44 f9 4d f5 a6 31 422 + ed e4 2c 17 19 bf da bf 02 53 fe 51 75 be 89 8e 423 + 75 0e dc 53 37 0d 2b 424 + |} 425 + 426 + let processed_payload () = 427 + let buf = 428 + let t = String.make 1 (Char.unsafe_chr (Tls.Packet.content_type_to_int Tls.Packet.HANDSHAKE)) in 429 + server_payload ^ t 430 + in 431 + let nonce = Tls.Crypto.aead_nonce write_handshake_iv 0L in 432 + let key = Mirage_crypto.AES.GCM.of_secret write_handshake_key in 433 + let adata = Tls.Writer.assemble_hdr `TLS_1_2 (Tls.Packet.APPLICATION_DATA, "") in 434 + Bytes.set_uint16_be (Bytes.unsafe_of_string adata) 3 (17 + String.length server_payload) ; 435 + let res = 436 + Mirage_crypto.AES.GCM.authenticate_encrypt ~key ~adata ~nonce buf 437 + in 438 + let data = Tls.Writer.assemble_hdr `TLS_1_2 (Tls.Packet.APPLICATION_DATA, res) in 439 + Alcotest.check cs __LOC__ server_payload_processed data 440 + 441 + let c_finished = Ohex.decode {| 442 + 14 00 00 20 a8 ec 43 6d 67 76 34 ae 52 5a c1 fc 443 + eb e1 1a 03 9e c1 76 94 fa c6 e9 85 27 b6 42 f2 444 + ed d5 ce 61 445 + |} 446 + 447 + let res_master = Ohex.decode {| 448 + 7d f2 35 f2 03 1d 2a 05 12 87 d0 2b 02 41 b0 bf 449 + da f8 6c c8 56 23 1f 2d 5a ba 46 c4 34 ec 19 6c 450 + |} 451 + 452 + let resumption () = 453 + let log = String.concat "" [ ch ; sh ; enc_ext ; cert ; cert_verify ; finished ; c_finished ] in 454 + let module H = (val Digestif.module_of_hash' hash) in 455 + let hash_val = H.(to_raw_string (digest_string log)) in 456 + Alcotest.check cs __LOC__ res_master 457 + (Tls.Handshake_crypto13.derive_secret_no_hash hash master_secret ~ctx:hash_val "res master") ; 458 + match !my_secret with 459 + | None -> Alcotest.fail "expected some secret" 460 + | Some s -> Alcotest.check cs __LOC__ res_master (Tls.Handshake_crypto13.resumption s log) 461 + 462 + let private_key = 463 + let _modulus = Ohex.decode {| 464 + b4 bb 49 8f 82 79 30 3d 98 08 36 39 9b 36 c6 98 465 + 8c 0c 68 de 55 e1 bd b8 26 d3 90 1a 24 61 ea fd 466 + 2d e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c 1a f1 467 + 9e aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 468 + cc b0 52 4b 1b 01 8c 3e 0b 63 26 4d 44 9a 6d 38 469 + e2 2a 5f da 43 08 46 74 80 30 53 0e f0 46 1c 8c 470 + a9 d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93 ef f0 ab 471 + 9a 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 472 + |} 473 + and public_exponent = Ohex.decode "01 00 01" 474 + and _private_exponent = Ohex.decode {| 475 + 04 de a7 05 d4 3a 6e a7 20 9d d8 07 21 11 a8 3c 476 + 81 e3 22 a5 92 78 b3 34 80 64 1e af 7c 0a 69 85 477 + b8 e3 1c 44 f6 de 62 e1 b4 c2 30 9f 61 26 e7 7b 478 + 7c 41 e9 23 31 4b bf a3 88 13 05 dc 12 17 f1 6c 479 + 81 9c e5 38 e9 22 f3 69 82 8d 0e 57 19 5d 8c 84 480 + 88 46 02 07 b2 fa a7 26 bc f7 08 bb d7 db 7f 67 481 + 9f 89 34 92 fc 2a 62 2e 08 97 0a ac 44 1c e4 e0 482 + c3 08 8d f2 5a e6 79 23 3d f8 a3 bd a2 ff 99 41 483 + |} 484 + and prime1 = Ohex.decode {| 485 + e4 35 fb 7c c8 37 37 75 6d ac ea 96 ab 7f 59 a2 486 + cc 10 69 db 7d eb 19 0e 17 e3 3a 53 2b 27 3f 30 487 + a3 27 aa 0a aa bc 58 cd 67 46 6a f9 84 5f ad c6 488 + 75 fe 09 4a f9 2c 4b d1 f2 c1 bc 33 dd 2e 05 15 489 + |} 490 + and prime2 = Ohex.decode {| 491 + ca bd 3b c0 e0 43 86 64 c8 d4 cc 9f 99 97 7a 94 492 + d9 bb fe ad 8e 43 87 0a ba e3 f7 eb 8b 4e 0e ee 493 + 8a f1 d9 b4 71 9b a6 19 6c f2 cb ba ee eb f8 b3 494 + 49 0a fe 9e 9f fa 74 a8 8a a5 1f c6 45 62 93 03 495 + |} 496 + and _exponent1 = Ohex.decode {| 497 + 3f 57 34 5c 27 fe 1b 68 7e 6e 76 16 27 b7 8b 1b 498 + 82 64 33 dd 76 0f a0 be a6 a6 ac f3 94 90 aa 1b 499 + 47 cd a4 86 9d 68 f5 84 dd 5b 50 29 bd 32 09 3b 500 + 82 58 66 1f e7 15 02 5e 5d 70 a4 5a 08 d3 d3 19 501 + |} 502 + and _exponent2 = Ohex.decode {| 503 + 18 3d a0 13 63 bd 2f 28 85 ca cb dc 99 64 bf 47 504 + 64 f1 51 76 36 f8 64 01 28 6f 71 89 3c 52 cc fe 505 + 40 a6 c2 3d 0d 08 6b 47 c6 fb 10 d8 fd 10 41 e0 506 + 4d ef 7e 9a 40 ce 95 7c 41 77 94 e1 04 12 d1 39 507 + |} 508 + and _coefficient = Ohex.decode {| 509 + 83 9c a9 a0 85 e4 28 6b 2c 90 e4 66 99 7a 2c 68 510 + 1f 21 33 9a a3 47 78 14 e4 de c1 18 33 05 0e d5 511 + 0d d1 3c c0 38 04 8a 43 c5 9b 2a cc 41 68 89 c0 512 + 37 66 5f e5 af a6 05 96 9f 8c 01 df a5 ca 96 9d 513 + |} 514 + in 515 + let e = Mirage_crypto_pk.Z_extra.of_octets_be public_exponent 516 + and p = Mirage_crypto_pk.Z_extra.of_octets_be prime1 517 + and q = Mirage_crypto_pk.Z_extra.of_octets_be prime2 518 + in 519 + match Mirage_crypto_pk.Rsa.priv_of_primes ~e ~p ~q with 520 + | Ok p -> p 521 + | Error (`Msg m) -> invalid_arg m 522 + 523 + let log = String.concat "" [ ch ; sh ; enc_ext ; cert ] 524 + and cert = match X509.Certificate.decode_der (String.sub cert 11 0x01b0) with 525 + | Ok c -> Some c 526 + | Error _ -> None 527 + 528 + let self_signature () = 529 + let module H = (val Digestif.module_of_hash' hash) in 530 + match 531 + Tls.Handshake_common.signature `TLS_1_3 532 + ~context_string:"TLS 1.3, server CertificateVerify" 533 + H.(to_raw_string (digest_string log)) 534 + (Some [ `RSA_PSS_RSAENC_SHA256 ]) [ `RSA_PSS_RSAENC_SHA256 ] 535 + (`RSA private_key) 536 + with 537 + | Error _ -> Alcotest.fail "expected sth" 538 + | Ok data -> 539 + match Tls.Handshake_common.verify_digitally_signed `TLS_1_3 540 + ~context_string:"TLS 1.3, server CertificateVerify" 541 + [ `RSA_PSS_RSAENC_SHA256 ] data 542 + H.(to_raw_string (digest_string log)) cert 543 + with 544 + | Ok () -> () 545 + | Error e -> Alcotest.fail ("self-verification failed " ^ Tls.Engine.string_of_failure e) 546 + 547 + let wire_signature () = 548 + (* let buf = Writer.assemble_handshake (CertificateVerify data) in 549 + Alcotest.check cs __LOC__ cert_verify buf *) 550 + let module H = (val Digestif.module_of_hash' hash) in 551 + match Tls.Handshake_common.verify_digitally_signed `TLS_1_3 552 + ~context_string:"TLS 1.3, server CertificateVerify" 553 + [ `RSA_PSS_RSAENC_SHA256 ] (String.sub cert_verify 4 (String.length cert_verify - 4)) 554 + H.(to_raw_string (digest_string log)) cert 555 + with 556 + | Ok () -> () 557 + | Error e -> Alcotest.fail ("trace-verification failed " ^ Tls.Engine.string_of_failure e) 558 + 559 + let res_secret_00 = Ohex.decode {| 560 + 4e cd 0e b6 ec 3b 4d 87 f5 d6 02 8f 92 2c a4 c5 561 + 85 1a 27 7f d4 13 11 c9 e6 2d 2c 94 92 e1 c4 f3 562 + |} 563 + 564 + let res_secret () = 565 + let nonce = String.make 2 '\x00' in 566 + Alcotest.check cs __LOC__ res_secret_00 567 + (Tls.Handshake_crypto13.derive_secret_no_hash hash res_master ~ctx:nonce "resumption") ; 568 + Alcotest.check cs __LOC__ res_secret_00 569 + (Tls.Handshake_crypto13.res_secret hash res_master nonce) 570 + 571 + 572 + let early_secret1 = Ohex.decode {| 573 + 9b 21 88 e9 b2 fc 6d 64 d7 1d c3 29 90 0e 20 bb 574 + 41 91 50 00 f6 78 aa 83 9c bb 79 7c b7 d8 33 2c 575 + |} 576 + 577 + let early1 () = 578 + let salt = "" 579 + and ikm = res_secret_00 580 + in 581 + Alcotest.check cs __LOC__ early_secret1 (Hkdf.extract ~hash ~salt ikm) ; 582 + let t = Tls.Handshake_crypto13.(derive (empty cipher) ikm) in 583 + my_secret := Some t ; 584 + Alcotest.check cs __LOC__ early_secret1 t.secret 585 + 586 + let ch_res_prefix = Ohex.decode {| 587 + 01 00 01 fc 03 03 1b c3 ce b6 bb e3 9c ff 93 83 588 + 55 b5 a5 0a db 6d b2 1b 7a 6a f6 49 d7 b4 bc 41 589 + 9d 78 76 48 7d 95 00 00 06 13 01 13 03 13 02 01 590 + 00 01 cd 00 00 00 0b 00 09 00 00 06 73 65 72 76 591 + 65 72 ff 01 00 01 00 00 0a 00 14 00 12 00 1d 00 592 + 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 593 + 33 00 26 00 24 00 1d 00 20 e4 ff b6 8a c0 5f 8d 594 + 96 c9 9d a2 66 98 34 6c 6b e1 64 82 ba dd da fe 595 + 05 1a 66 b4 f1 8d 66 8f 0b 00 2a 00 00 00 2b 00 596 + 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03 06 03 597 + 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 598 + 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 599 + 00 02 40 01 00 15 00 57 00 00 00 00 00 00 00 00 600 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 601 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 602 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 603 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 604 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 605 + 29 00 dd 00 b8 00 b2 2c 03 5d 82 93 59 ee 5f f7 606 + af 4e c9 00 00 00 00 26 2a 64 94 dc 48 6d 2c 8a 607 + 34 cb 33 fa 90 bf 1b 00 70 ad 3c 49 88 83 c9 36 608 + 7c 09 a2 be 78 5a bc 55 cd 22 60 97 a3 a9 82 11 609 + 72 83 f8 2a 03 a1 43 ef d3 ff 5d d3 6d 64 e8 61 610 + be 7f d6 1d 28 27 db 27 9c ce 14 50 77 d4 54 a3 611 + 66 4d 4e 6d a4 d2 9e e0 37 25 a6 a4 da fc d0 fc 612 + 67 d2 ae a7 05 29 51 3e 3d a2 67 7f a5 90 6c 5b 613 + 3f 7d 8f 92 f2 28 bd a4 0d da 72 14 70 f9 fb f2 614 + 97 b5 ae a6 17 64 6f ac 5c 03 27 2e 97 07 27 c6 615 + 21 a7 91 41 ef 5f 7d e6 50 5e 5b fb c3 88 e9 33 616 + 43 69 40 93 93 4a e4 d3 57 fa d6 aa cb 617 + |} 618 + 619 + let binder () = 620 + let module H = (val Digestif.module_of_hash' hash) in 621 + let binder_hash = Ohex.decode "63 22 4b 2e 45 73 f2 d3 45 4c a8 4b 9d 00 9a 04 f6 be 9e 05 71 1a 83 96 47 3a ef a0 1e 92 4a 14" in 622 + Alcotest.check cs __LOC__ binder_hash H.(to_raw_string (digest_string ch_res_prefix)) ; 623 + match !my_secret with 624 + | None -> Alcotest.fail "expected secret" 625 + | Some s -> 626 + let prk = Ohex.decode "69 fe 13 1a 3b ba d5 d6 3c 64 ee bc c3 0e 39 5b 9d 81 07 72 6a 13 d0 74 e3 89 db c8 a4 e4 72 56" in 627 + Alcotest.check cs __LOC__ prk (Tls.Handshake_crypto13.derive_secret s "res binder" "") ; 628 + let finished = Ohex.decode "3a dd 4f b2 d8 fd f8 22 a0 ca 3c f7 67 8e f5 e8 8d ae 99 01 41 c5 92 4d 57 bb 6f a3 1b 9e 5f 9d" in 629 + Alcotest.check cs __LOC__ finished (Tls.Handshake_crypto13.finished hash prk ch_res_prefix) 630 + 631 + let x25519 () = 632 + let c_priv = Ohex.decode {| 633 + 49 af 42 ba 7f 79 94 85 2d 71 3e f2 78 4b cb ca 634 + a7 91 1d e2 6a dc 56 42 cb 63 45 40 e7 ea 50 05 635 + |} 636 + and c_keyshare = Ohex.decode {| 637 + 99 38 1d e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe 638 + b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af 2c 639 + |} 640 + and s_priv = Ohex.decode {| 641 + b1 58 0e ea df 6d d5 89 b8 ef 4f 2d 56 52 57 8c 642 + c8 10 e9 98 01 91 ec 8d 05 83 08 ce a2 16 a2 1e 643 + |} 644 + and s_keyshare = Ohex.decode {| 645 + c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 646 + 56 d6 cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 647 + |} 648 + in 649 + let check_pub pr pu = 650 + match Mirage_crypto_ec.X25519.secret_of_octets pr with 651 + | Ok (_, pub) -> Alcotest.check cs __LOC__ pu pub 652 + | Error _ -> Alcotest.fail "couldn't decode DH secret" 653 + in 654 + let check_one p ks = 655 + match Mirage_crypto_ec.X25519.secret_of_octets p with 656 + | Error _ -> Alcotest.fail "couldn't decode DH secret" 657 + | Ok (priv, _) -> 658 + match Mirage_crypto_ec.X25519.key_exchange priv ks with 659 + | Ok shared -> Alcotest.check cs __LOC__ ikm shared 660 + | Error _ -> Alcotest.fail "bad kex" 661 + in 662 + check_one c_priv s_keyshare ; 663 + check_one s_priv c_keyshare ; 664 + check_pub c_priv c_keyshare ; 665 + check_pub s_priv s_keyshare 666 + 667 + let tests = [ 668 + "initial extract", `Quick, extract_secret_early ; 669 + "initial derive", `Quick, derive_hs_secret ; 670 + "handshake extract", `Quick, extract_handshake ; 671 + "derive c hs", `Quick, derive_c_hs_traffic ; 672 + "derive s hs", `Quick, derive_s_hs_traffic ; 673 + "derive finished", `Quick, derive_finished ; 674 + "derive master", `Quick, derive_master ; 675 + "extract master", `Quick, extract_master ; 676 + "derive handshake keys", `Quick, derive_write_handshake_keys ; 677 + "derive traffic keys", `Quick, derive_traffic_keys ; 678 + "application write keys", `Quick, appdata_write ; 679 + "application read keys", `Quick, appdata_read ; 680 + "hs read keys", `Quick, derive_read_handshake_keys ; 681 + "resumption key", `Quick, resumption ; 682 + "payload", `Quick, payload_is_good ; 683 + "processed payload", `Quick, processed_payload ; 684 + "self signature", `Quick, self_signature ; 685 + "wire signature", `Quick, wire_signature ; 686 + "res secret", `Quick, res_secret ; 687 + "early resumed", `Quick, early1 ; 688 + "binder", `Quick, binder ; 689 + "x25519", `Quick, x25519 ; 690 + ] 691 + 692 + let () = 693 + Fmt_tty.setup_std_outputs (); 694 + Logs.set_level (Some Logs.Debug); 695 + Logs.set_reporter (Logs_fmt.reporter ~dst:Format.std_formatter ()) ; 696 + Mirage_crypto_rng_unix.use_default () ; 697 + Alcotest.run "Key derivation tests" [ "key extraction and derivation", tests ]
+1553
vendor/opam/tls/tests/readertests.ml
··· 1 + open Tls 2 + open OUnit2 3 + open Testlib 4 + 5 + let good_any_version_parser major minor result _ = 6 + let ver = list_to_cstruct [ major ; minor ] in 7 + match Reader.parse_any_version ver with 8 + | Ok v -> assert_equal v result 9 + | Error _ -> assert_failure "Version parser broken" 10 + 11 + let bad_any_version_parser major minor _ = 12 + let ver = list_to_cstruct [ major ; minor ] in 13 + match Reader.parse_any_version ver with 14 + | Ok _ -> assert_failure "Version parser broken" 15 + | Error _ -> () 16 + 17 + let parse_any_version_too_short _ = 18 + let ver = list_to_cstruct [ 0 ] in 19 + match Reader.parse_any_version ver with 20 + | Ok _ -> assert_failure "Version parser broken" 21 + | Error _ -> () 22 + 23 + let any_version_parser_tests = [ 24 + good_any_version_parser 3 0 `SSL_3 ; 25 + good_any_version_parser 3 1 `TLS_1_0 ; 26 + good_any_version_parser 3 2 `TLS_1_1 ; 27 + good_any_version_parser 3 3 `TLS_1_2 ; 28 + good_any_version_parser 3 4 `TLS_1_3 ; 29 + good_any_version_parser 3 42 (`TLS_1_X 42); 30 + 31 + bad_any_version_parser 2 4 ; 32 + bad_any_version_parser 4 4 ; 33 + bad_any_version_parser 0 2 ; 34 + 35 + parse_any_version_too_short 36 + ] 37 + 38 + let any_version_tests = 39 + List.mapi 40 + (fun i f -> "Parse any version " ^ string_of_int i >:: f) 41 + any_version_parser_tests 42 + 43 + let good_version_parser major minor result _ = 44 + let ver = list_to_cstruct [ major ; minor ] in 45 + match Reader.parse_version ver with 46 + | Ok v -> assert_equal v result 47 + | Error _ -> assert_failure "Version parser broken" 48 + 49 + let bad_version_parser major minor _ = 50 + let ver = list_to_cstruct [ major ; minor ] in 51 + match Reader.parse_version ver with 52 + | Ok _ -> assert_failure "Version parser broken" 53 + | Error _ -> () 54 + 55 + let parse_version_too_short _ = 56 + let ver = list_to_cstruct [ 0 ] in 57 + match Reader.parse_version ver with 58 + | Ok _ -> assert_failure "Version parser broken" 59 + | Error _ -> () 60 + 61 + let version_parser_tests = [ 62 + good_version_parser 3 1 `TLS_1_0 ; 63 + good_version_parser 3 2 `TLS_1_1 ; 64 + good_version_parser 3 3 `TLS_1_2 ; 65 + good_version_parser 3 4 `TLS_1_3 ; 66 + 67 + bad_version_parser 3 0 ; 68 + bad_version_parser 3 42 ; 69 + bad_version_parser 2 4 ; 70 + bad_version_parser 4 4 ; 71 + bad_version_parser 0 2 ; 72 + 73 + parse_version_too_short 74 + ] 75 + 76 + let version_tests = 77 + List.mapi 78 + (fun i f -> "Parse version " ^ string_of_int i >:: f) 79 + version_parser_tests 80 + 81 + 82 + let good_record_parser (bytes, result) _ = 83 + let buf = list_to_cstruct bytes in 84 + let open Reader in 85 + match parse_record buf, result with 86 + | Ok (`Record ((hdr, x), f)), `Record ((rhdr, y), g) -> 87 + assert_equal rhdr hdr ; 88 + assert_cs_eq y x ; 89 + assert_cs_eq g f 90 + | Ok `Fragment x, `Fragment y -> assert_cs_eq y x 91 + | Error `Record_overflow x, `Overflow y -> assert_equal y x 92 + | Error `Protocol_version `Unknown_record x, `UnknownVersion y -> assert_equal y x 93 + | Error `Unexpected `Content_type x, `UnknownContent y -> assert_equal y x 94 + | _ -> assert_failure "record parser broken" 95 + 96 + let good_records = 97 + let open Core in 98 + let open Packet in 99 + let empty = "" in 100 + [ 101 + ([ 20 ; 3 ; 1 ; 0 ; 0 ], `Record (({ content_type = CHANGE_CIPHER_SPEC ; version = `TLS_1_0 }, empty), empty) ) ; 102 + ([ 21 ; 3 ; 2 ; 0 ; 0 ], `Record (({ content_type = ALERT ; version = `TLS_1_1 }, empty), empty) ) ; 103 + ([ 22 ; 3 ; 3 ; 0 ; 0 ], `Record (({ content_type = HANDSHAKE ; version = `TLS_1_2 }, empty), empty) ) ; 104 + ([ 23 ; 3 ; 0 ; 0 ; 0 ], `Record (({ content_type = APPLICATION_DATA ; version = `SSL_3 }, empty), empty) ) ; 105 + ([ 16 ; 3 ; 1 ; 0 ; 0 ], `UnknownContent 16 ) ; 106 + ([ 19 ; 3 ; 1 ; 0 ; 0 ], `UnknownContent 19 ) ; 107 + ([ 20 ; 5 ; 1 ; 0 ; 0 ], `UnknownVersion (5, 1) ) ; 108 + ([ 20 ; 3 ; 1 ; 0 ; 100 ], `Fragment (list_to_cstruct [ 20 ; 3 ; 1 ; 0 ; 100 ] )) ; 109 + ([ 0 ], `Fragment (list_to_cstruct [ 0 ])) ; 110 + ([ ], `Fragment empty) ; 111 + ([ 20 ; 3 ; 1 ; 0 ; 0 ; 0 ], `Record (({ content_type = CHANGE_CIPHER_SPEC ; version = `TLS_1_0 }, empty), list_to_cstruct [ 0 ]) ) ; 112 + ([ 0 ; 0 ; 0 ; 255 ; 255 ], `Overflow 65535) ; 113 + ([ 0 ; 0 ; 0 ; 72 ; 1 ], `Overflow 18433) 114 + ] 115 + 116 + let good_records_tests = 117 + List.mapi 118 + (fun i args -> "Good record " ^ string_of_int i >:: good_record_parser args) 119 + good_records 120 + 121 + let good_alert_parser (lvl, typ, expected) _ = 122 + let buf = list_to_cstruct [ lvl ; typ ] in 123 + match Reader.parse_alert buf with 124 + | Ok al -> assert_equal al expected 125 + | Error _ -> assert_failure "alert parser broken" 126 + 127 + let good_alerts = 128 + let w = Packet.WARNING in 129 + let f = Packet.FATAL in 130 + [ 131 + (1, 0, (w, Packet.CLOSE_NOTIFY)); 132 + (2, 0, (f, Packet.CLOSE_NOTIFY)); 133 + (* (1, 10, (w, Packet.UNEXPECTED_MESSAGE)); *) 134 + (2, 10, (f, Packet.UNEXPECTED_MESSAGE)); 135 + (* (1, 20, (w, Packet.BAD_RECORD_MAC)); *) 136 + (2, 20, (f, Packet.BAD_RECORD_MAC)); 137 + (* (1, 22, (w, Packet.RECORD_OVERFLOW)); *) 138 + (2, 22, (f, Packet.RECORD_OVERFLOW)); 139 + (* (1, 40, (w, Packet.HANDSHAKE_FAILURE)); *) 140 + (2, 40, (f, Packet.HANDSHAKE_FAILURE)); 141 + (* (1, 42, (w, Packet.BAD_CERTIFICATE)); *) 142 + (2, 42, (f, Packet.BAD_CERTIFICATE)); 143 + (1, 45, (w, Packet.CERTIFICATE_EXPIRED)); 144 + (2, 45, (f, Packet.CERTIFICATE_EXPIRED)); 145 + (* (1, 50, (w, Packet.DECODE_ERROR)); *) 146 + (2, 50, (f, Packet.DECODE_ERROR)); 147 + (* (1, 70, (w, Packet.PROTOCOL_VERSION)); *) 148 + (2, 70, (f, Packet.PROTOCOL_VERSION)); 149 + (1, 90, (w, Packet.USER_CANCELED)); 150 + (* (2, 90, (f, Packet.USER_CANCELED)); *) 151 + (1, 100, (w, Packet.NO_RENEGOTIATION)); 152 + (* (2, 100, (f, Packet.NO_RENEGOTIATION)); *) 153 + (* (1, 110, (w, Packet.UNSUPPORTED_EXTENSION)); *) 154 + (2, 110, (f, Packet.UNSUPPORTED_EXTENSION)); 155 + (* (1, 112, (w, Packet.UNRECOGNIZED_NAME)); *) 156 + (2, 112, (f, Packet.UNRECOGNIZED_NAME)); 157 + (2, 120, (f, Packet.NO_APPLICATION_PROTOCOL)); 158 + ] 159 + 160 + let good_alert_tests = 161 + List.mapi 162 + (fun i args -> "Good alert " ^ string_of_int i >:: good_alert_parser args) 163 + good_alerts 164 + 165 + let alert_too_small _ = 166 + let buf = list_to_cstruct [ 0 ] in 167 + match Reader.parse_alert buf with 168 + | Ok _ -> assert_failure "short alert passes" 169 + | Error _ -> () 170 + 171 + let alert_too_small2 _ = 172 + let buf = list_to_cstruct [ 25 ] in 173 + match Reader.parse_alert buf with 174 + | Ok _ -> assert_failure "short alert passes" 175 + | Error _ -> () 176 + 177 + let bad_alerts_tests = 178 + [ ("short alert" >:: alert_too_small) ; 179 + ("short alert 2" >:: alert_too_small2) ] 180 + 181 + let good_dhparams = [ 182 + [ 183 + 0x01; 0x00; 0xf6; 0x42; 0x57; 0xb7; 0x08; 0x7f; 0x08; 0x17; 0x72; 0xa2; 0xba; 0xd6; 0xa9; 0x42; 184 + 0xf3; 0x05; 0xe8; 0xf9; 0x53; 0x11; 0x39; 0x4f; 0xb6; 0xf1; 0x6e; 0xb9; 0x4b; 0x38; 0x20; 0xda; 185 + 0x01; 0xa7; 0x56; 0xa3; 0x14; 0xe9; 0x8f; 0x40; 0x55; 0xf3; 0xd0; 0x07; 0xc6; 0xcb; 0x43; 0xa9; 186 + 0x94; 0xad; 0xf7; 0x4c; 0x64; 0x86; 0x49; 0xf8; 0x0c; 0x83; 0xbd; 0x65; 0xe9; 0x17; 0xd4; 0xa1; 187 + 0xd3; 0x50; 0xf8; 0xf5; 0x59; 0x5f; 0xdc; 0x76; 0x52; 0x4f; 0x3d; 0x3d; 0x8d; 0xdb; 0xce; 0x99; 188 + 0xe1; 0x57; 0x92; 0x59; 0xcd; 0xfd; 0xb8; 0xae; 0x74; 0x4f; 0xc5; 0xfc; 0x76; 0xbc; 0x83; 0xc5; 189 + 0x47; 0x30; 0x61; 0xce; 0x7c; 0xc9; 0x66; 0xff; 0x15; 0xf9; 0xbb; 0xfd; 0x91; 0x5e; 0xc7; 0x01; 190 + 0xaa; 0xd3; 0x5b; 0x9e; 0x8d; 0xa0; 0xa5; 0x72; 0x3a; 0xd4; 0x1a; 0xf0; 0xbf; 0x46; 0x00; 0x58; 191 + 0x2b; 0xe5; 0xf4; 0x88; 0xfd; 0x58; 0x4e; 0x49; 0xdb; 0xcd; 0x20; 0xb4; 0x9d; 0xe4; 0x91; 0x07; 192 + 0x36; 0x6b; 0x33; 0x6c; 0x38; 0x0d; 0x45; 0x1d; 0x0f; 0x7c; 0x88; 0xb3; 0x1c; 0x7c; 0x5b; 0x2d; 193 + 0x8e; 0xf6; 0xf3; 0xc9; 0x23; 0xc0; 0x43; 0xf0; 0xa5; 0x5b; 0x18; 0x8d; 0x8e; 0xbb; 0x55; 0x8c; 194 + 0xb8; 0x5d; 0x38; 0xd3; 0x34; 0xfd; 0x7c; 0x17; 0x57; 0x43; 0xa3; 0x1d; 0x18; 0x6c; 0xde; 0x33; 195 + 0x21; 0x2c; 0xb5; 0x2a; 0xff; 0x3c; 0xe1; 0xb1; 0x29; 0x40; 0x18; 0x11; 0x8d; 0x7c; 0x84; 0xa7; 196 + 0x0a; 0x72; 0xd6; 0x86; 0xc4; 0x03; 0x19; 0xc8; 0x07; 0x29; 0x7a; 0xca; 0x95; 0x0c; 0xd9; 0x96; 197 + 0x9f; 0xab; 0xd0; 0x0a; 0x50; 0x9b; 0x02; 0x46; 0xd3; 0x08; 0x3d; 0x66; 0xa4; 0x5d; 0x41; 0x9f; 198 + 0x9c; 0x7c; 0xbd; 0x89; 0x4b; 0x22; 0x19; 0x26; 0xba; 0xab; 0xa2; 0x5e; 0xc3; 0x55; 0xe9; 0x32; 199 + 0x0b; 0x3b; 0x00; 0x01; 0x02; 0x01; 0x00; 0x54; 0x7d; 0x06; 0xfb; 0x28; 0xe3; 0x64; 0x86; 0x53; 200 + 0x6e; 0xf0; 0xfc; 0xdc; 0x57; 0xb6; 0x86; 0xae; 0xa7; 0x20; 0xbc; 0xac; 0x76; 0x38; 0xf5; 0x64; 201 + 0x02; 0x9d; 0x19; 0x1a; 0xfe; 0x4d; 0x0d; 0x5a; 0xd3; 0xc6; 0x76; 0x9b; 0x33; 0x8d; 0x3a; 0x96; 202 + 0xcc; 0x3f; 0x72; 0xdf; 0x1d; 0x19; 0xd2; 0x61; 0x41; 0x95; 0x3a; 0x2d; 0x83; 0x7f; 0x4e; 0xbb; 203 + 0x48; 0xf4; 0x77; 0x05; 0xd3; 0x23; 0xff; 0x49; 0xd8; 0xc8; 0x70; 0x0a; 0x69; 0xd4; 0xf7; 0x64; 204 + 0xfa; 0x86; 0x8c; 0x94; 0x96; 0x41; 0x14; 0xf1; 0x6e; 0x6f; 0x09; 0x21; 0x2b; 0xd5; 0xfa; 0x52; 205 + 0x56; 0xf4; 0x44; 0x25; 0x29; 0xb2; 0x51; 0x4e; 0x57; 0xd7; 0x8b; 0xcb; 0x70; 0x3b; 0x94; 0x4f; 206 + 0x2b; 0xe2; 0xa7; 0xfc; 0xaa; 0x09; 0xd0; 0x82; 0x9e; 0xa8; 0x17; 0xbe; 0x84; 0xf0; 0x1a; 0xae; 207 + 0xe1; 0x97; 0x14; 0x7b; 0x74; 0xd4; 0x12; 0xf8; 0x96; 0xbe; 0xa9; 0x2e; 0xdd; 0xbe; 0x28; 0xcd; 208 + 0xe8; 0x9f; 0x67; 0x31; 0x98; 0xcb; 0x74; 0xae; 0xd4; 0x50; 0xa5; 0x77; 0xc4; 0xc1; 0x39; 0x9c; 209 + 0xcd; 0xc2; 0x8a; 0xfe; 0xe2; 0x77; 0x1c; 0x09; 0x75; 0x3e; 0xf7; 0x96; 0x6a; 0x92; 0x96; 0x06; 210 + 0x1e; 0x8d; 0x22; 0xdd; 0x58; 0xfe; 0x3d; 0x84; 0x56; 0x09; 0x17; 0xe2; 0x50; 0xb1; 0xf6; 0x61; 211 + 0x54; 0x6e; 0x5e; 0x94; 0xca; 0xf0; 0x40; 0x68; 0x84; 0xeb; 0xc1; 0x0c; 0x43; 0x3e; 0xbc; 0xb3; 212 + 0x0e; 0x81; 0x4d; 0xc0; 0x21; 0xdb; 0x97; 0xc6; 0x8b; 0x27; 0x10; 0x5c; 0xae; 0xe3; 0x6e; 0x66; 213 + 0x85; 0xaf; 0xff; 0x19; 0x8b; 0xf8; 0xd5; 0x93; 0x4b; 0xd2; 0xd8; 0x7c; 0x64; 0x04; 0xed; 0xce; 214 + 0x88; 0xce; 0xb8; 0x2c; 0x4f; 0xe0; 0xf5; 0x0d; 0x3a; 0xeb; 0x78; 0xee; 0xcf; 0x1a; 0xd1; 0x02; 215 + 0xcf; 0x0f; 0x68; 0xed; 0xd2; 0xca; 0xf6 216 + 217 + ] ; [ 218 + 219 + 0x01; 0x00; 0xf6; 0x42; 0x57; 0xb7; 0x08; 0x7f; 0x08; 0x17; 0x72; 0xa2; 0xba; 0xd6; 0xa9; 0x42; 220 + 0xf3; 0x05; 0xe8; 0xf9; 0x53; 0x11; 0x39; 0x4f; 0xb6; 0xf1; 0x6e; 0xb9; 0x4b; 0x38; 0x20; 0xda; 221 + 0x01; 0xa7; 0x56; 0xa3; 0x14; 0xe9; 0x8f; 0x40; 0x55; 0xf3; 0xd0; 0x07; 0xc6; 0xcb; 0x43; 0xa9; 222 + 0x94; 0xad; 0xf7; 0x4c; 0x64; 0x86; 0x49; 0xf8; 0x0c; 0x83; 0xbd; 0x65; 0xe9; 0x17; 0xd4; 0xa1; 223 + 0xd3; 0x50; 0xf8; 0xf5; 0x59; 0x5f; 0xdc; 0x76; 0x52; 0x4f; 0x3d; 0x3d; 0x8d; 0xdb; 0xce; 0x99; 224 + 0xe1; 0x57; 0x92; 0x59; 0xcd; 0xfd; 0xb8; 0xae; 0x74; 0x4f; 0xc5; 0xfc; 0x76; 0xbc; 0x83; 0xc5; 225 + 0x47; 0x30; 0x61; 0xce; 0x7c; 0xc9; 0x66; 0xff; 0x15; 0xf9; 0xbb; 0xfd; 0x91; 0x5e; 0xc7; 0x01; 226 + 0xaa; 0xd3; 0x5b; 0x9e; 0x8d; 0xa0; 0xa5; 0x72; 0x3a; 0xd4; 0x1a; 0xf0; 0xbf; 0x46; 0x00; 0x58; 227 + 0x2b; 0xe5; 0xf4; 0x88; 0xfd; 0x58; 0x4e; 0x49; 0xdb; 0xcd; 0x20; 0xb4; 0x9d; 0xe4; 0x91; 0x07; 228 + 0x36; 0x6b; 0x33; 0x6c; 0x38; 0x0d; 0x45; 0x1d; 0x0f; 0x7c; 0x88; 0xb3; 0x1c; 0x7c; 0x5b; 0x2d; 229 + 0x8e; 0xf6; 0xf3; 0xc9; 0x23; 0xc0; 0x43; 0xf0; 0xa5; 0x5b; 0x18; 0x8d; 0x8e; 0xbb; 0x55; 0x8c; 230 + 0xb8; 0x5d; 0x38; 0xd3; 0x34; 0xfd; 0x7c; 0x17; 0x57; 0x43; 0xa3; 0x1d; 0x18; 0x6c; 0xde; 0x33; 231 + 0x21; 0x2c; 0xb5; 0x2a; 0xff; 0x3c; 0xe1; 0xb1; 0x29; 0x40; 0x18; 0x11; 0x8d; 0x7c; 0x84; 0xa7; 232 + 0x0a; 0x72; 0xd6; 0x86; 0xc4; 0x03; 0x19; 0xc8; 0x07; 0x29; 0x7a; 0xca; 0x95; 0x0c; 0xd9; 0x96; 233 + 0x9f; 0xab; 0xd0; 0x0a; 0x50; 0x9b; 0x02; 0x46; 0xd3; 0x08; 0x3d; 0x66; 0xa4; 0x5d; 0x41; 0x9f; 234 + 0x9c; 0x7c; 0xbd; 0x89; 0x4b; 0x22; 0x19; 0x26; 0xba; 0xab; 0xa2; 0x5e; 0xc3; 0x55; 0xe9; 0x32; 235 + 0x0b; 0x3b; 0x00; 0x01; 0x02; 0x01; 0x00; 0x7d; 0x17; 0xb3; 0xc8; 0x40; 0xcd; 0xa0; 0x75; 0x5b; 236 + 0xa4; 0xe1; 0xed; 0xef; 0xd3; 0xed; 0x74; 0x8e; 0x3c; 0xd5; 0x37; 0x17; 0xe2; 0x2b; 0x3d; 0x4e; 237 + 0x20; 0x2b; 0xf4; 0xdc; 0x83; 0x5a; 0x8b; 0x86; 0xed; 0x7b; 0xa3; 0x8d; 0xfa; 0xb4; 0x3a; 0x72; 238 + 0x95; 0xca; 0x5a; 0xd9; 0xf9; 0x27; 0x08; 0x10; 0xec; 0x9b; 0x9b; 0x86; 0xad; 0xbe; 0xfe; 0x77; 239 + 0xcb; 0xf7; 0xf6; 0x03; 0x35; 0x9f; 0x16; 0x97; 0x72; 0x6e; 0x92; 0xb8; 0xd7; 0xd3; 0x09; 0x58; 240 + 0x1d; 0xd0; 0x8a; 0xeb; 0x16; 0xa9; 0x71; 0x9a; 0xf8; 0xb6; 0xc8; 0xcc; 0x63; 0x52; 0x8d; 0x8f; 241 + 0x93; 0x23; 0x1b; 0xa8; 0xfe; 0x3c; 0x17; 0x9b; 0xe6; 0x64; 0x3d; 0xab; 0x57; 0x0c; 0xb1; 0x17; 242 + 0x71; 0xc1; 0x40; 0x72; 0xc9; 0x42; 0x43; 0x68; 0x39; 0xa5; 0x7f; 0x63; 0x03; 0x7e; 0xff; 0xd6; 243 + 0x11; 0xe1; 0x1a; 0xe1; 0xd9; 0x2f; 0xa3; 0x4a; 0x93; 0x4f; 0x09; 0x79; 0xbd; 0x78; 0xf3; 0xf4; 244 + 0xe1; 0x44; 0x7d; 0xaf; 0x7b; 0xd7; 0x82; 0x11; 0xc9; 0xd9; 0x91; 0x01; 0x9a; 0x2c; 0xcb; 0xd1; 245 + 0x41; 0xcc; 0xf5; 0x5c; 0x9f; 0xb5; 0xa2; 0x7c; 0x8b; 0x2d; 0xf6; 0x16; 0xab; 0x68; 0x99; 0x99; 246 + 0x33; 0x80; 0x72; 0xee; 0xce; 0x13; 0xea; 0x3f; 0x62; 0xca; 0xfc; 0x56; 0xd6; 0x6d; 0xa2; 0x8a; 247 + 0xfe; 0xdf; 0x71; 0x7a; 0x82; 0x39; 0xd1; 0x5d; 0x09; 0x27; 0x26; 0x26; 0x5c; 0x6e; 0xab; 0x28; 248 + 0xb2; 0xa1; 0x6f; 0xb9; 0x08; 0x25; 0xd0; 0xa1; 0x68; 0x25; 0x31; 0xae; 0x4a; 0xef; 0x62; 0x99; 249 + 0xb6; 0x4d; 0xd2; 0xa9; 0x27; 0x20; 0x99; 0xc4; 0xdc; 0x44; 0x81; 0x0c; 0xc0; 0xfe; 0xa9; 0xab; 250 + 0xc9; 0xe8; 0x26; 0x00; 0x60; 0x40; 0x0e; 0xb4; 0x07; 0xfc; 0xcf; 0x7f; 0x93; 0xc5; 0x20; 0x10; 251 + 0x49; 0x72; 0xd2; 0x9b; 0x4b; 0x70; 0x03 252 + 253 + ] ; [ 254 + 255 + 0x01; 0x00; 0xf6; 0x42; 0x57; 0xb7; 0x08; 0x7f; 0x08; 0x17; 0x72; 0xa2; 0xba; 0xd6; 0xa9; 0x42; 256 + 0xf3; 0x05; 0xe8; 0xf9; 0x53; 0x11; 0x39; 0x4f; 0xb6; 0xf1; 0x6e; 0xb9; 0x4b; 0x38; 0x20; 0xda; 257 + 0x01; 0xa7; 0x56; 0xa3; 0x14; 0xe9; 0x8f; 0x40; 0x55; 0xf3; 0xd0; 0x07; 0xc6; 0xcb; 0x43; 0xa9; 258 + 0x94; 0xad; 0xf7; 0x4c; 0x64; 0x86; 0x49; 0xf8; 0x0c; 0x83; 0xbd; 0x65; 0xe9; 0x17; 0xd4; 0xa1; 259 + 0xd3; 0x50; 0xf8; 0xf5; 0x59; 0x5f; 0xdc; 0x76; 0x52; 0x4f; 0x3d; 0x3d; 0x8d; 0xdb; 0xce; 0x99; 260 + 0xe1; 0x57; 0x92; 0x59; 0xcd; 0xfd; 0xb8; 0xae; 0x74; 0x4f; 0xc5; 0xfc; 0x76; 0xbc; 0x83; 0xc5; 261 + 0x47; 0x30; 0x61; 0xce; 0x7c; 0xc9; 0x66; 0xff; 0x15; 0xf9; 0xbb; 0xfd; 0x91; 0x5e; 0xc7; 0x01; 262 + 0xaa; 0xd3; 0x5b; 0x9e; 0x8d; 0xa0; 0xa5; 0x72; 0x3a; 0xd4; 0x1a; 0xf0; 0xbf; 0x46; 0x00; 0x58; 263 + 0x2b; 0xe5; 0xf4; 0x88; 0xfd; 0x58; 0x4e; 0x49; 0xdb; 0xcd; 0x20; 0xb4; 0x9d; 0xe4; 0x91; 0x07; 264 + 0x36; 0x6b; 0x33; 0x6c; 0x38; 0x0d; 0x45; 0x1d; 0x0f; 0x7c; 0x88; 0xb3; 0x1c; 0x7c; 0x5b; 0x2d; 265 + 0x8e; 0xf6; 0xf3; 0xc9; 0x23; 0xc0; 0x43; 0xf0; 0xa5; 0x5b; 0x18; 0x8d; 0x8e; 0xbb; 0x55; 0x8c; 266 + 0xb8; 0x5d; 0x38; 0xd3; 0x34; 0xfd; 0x7c; 0x17; 0x57; 0x43; 0xa3; 0x1d; 0x18; 0x6c; 0xde; 0x33; 267 + 0x21; 0x2c; 0xb5; 0x2a; 0xff; 0x3c; 0xe1; 0xb1; 0x29; 0x40; 0x18; 0x11; 0x8d; 0x7c; 0x84; 0xa7; 268 + 0x0a; 0x72; 0xd6; 0x86; 0xc4; 0x03; 0x19; 0xc8; 0x07; 0x29; 0x7a; 0xca; 0x95; 0x0c; 0xd9; 0x96; 269 + 0x9f; 0xab; 0xd0; 0x0a; 0x50; 0x9b; 0x02; 0x46; 0xd3; 0x08; 0x3d; 0x66; 0xa4; 0x5d; 0x41; 0x9f; 270 + 0x9c; 0x7c; 0xbd; 0x89; 0x4b; 0x22; 0x19; 0x26; 0xba; 0xab; 0xa2; 0x5e; 0xc3; 0x55; 0xe9; 0x32; 271 + 0x0b; 0x3b; 0x00; 0x01; 0x02; 0x01; 0x00; 0x4e; 0x72; 0x1e; 0x54; 0x1d; 0x3b; 0x3c; 0xad; 0xc7; 272 + 0x42; 0xf4; 0x2b; 0xcc; 0xce; 0xc9; 0x71; 0x4a; 0x85; 0xa1; 0x21; 0xda; 0x81; 0x40; 0x6a; 0xeb; 273 + 0x8a; 0x0a; 0x0f; 0xca; 0x73; 0x32; 0x5f; 0xa9; 0x5c; 0x24; 0x21; 0x1d; 0x1d; 0xd6; 0x10; 0xe0; 274 + 0x7f; 0x9e; 0xc4; 0x86; 0x2f; 0xa3; 0xcc; 0xc2; 0x60; 0x5d; 0xed; 0x7f; 0x7d; 0xb7; 0xa2; 0x96; 275 + 0x4f; 0xe6; 0x81; 0x1b; 0x29; 0xf9; 0xf4; 0xc1; 0x00; 0x46; 0x68; 0x4d; 0x72; 0x0e; 0x36; 0x21; 276 + 0xc3; 0x46; 0xf2; 0x81; 0x83; 0xed; 0x30; 0x89; 0x3f; 0xd8; 0x98; 0x39; 0xe5; 0x46; 0x90; 0xeb; 277 + 0x68; 0xe6; 0x3b; 0x8f; 0xc5; 0xd3; 0xa7; 0xfe; 0x87; 0xd7; 0x14; 0x33; 0x5b; 0x70; 0x82; 0x82; 278 + 0x57; 0x2f; 0xd8; 0xb2; 0x91; 0xc3; 0xe5; 0x19; 0x15; 0x5b; 0x76; 0xe6; 0x94; 0x1a; 0xe9; 0x11; 279 + 0x2c; 0xa5; 0x57; 0x55; 0xf0; 0x20; 0x36; 0xc9; 0xe1; 0x32; 0x94; 0x26; 0x47; 0xb8; 0x10; 0x40; 280 + 0xc0; 0x47; 0xf6; 0x66; 0x53; 0x49; 0xe3; 0x85; 0xe1; 0x0e; 0x1e; 0xba; 0xc0; 0xb8; 0x97; 0x8b; 281 + 0x16; 0x8e; 0x48; 0x71; 0xdd; 0x88; 0x3a; 0x8b; 0x21; 0x89; 0xeb; 0x28; 0x8d; 0xaa; 0x97; 0xcf; 282 + 0x4a; 0x45; 0xa4; 0xb8; 0x7d; 0x0f; 0x1e; 0x29; 0xc1; 0xe2; 0xc3; 0x75; 0x43; 0xb5; 0xbf; 0xcf; 283 + 0x14; 0xa4; 0xea; 0x3e; 0xe5; 0x94; 0x0c; 0x32; 0x8a; 0x91; 0xcb; 0x47; 0x7f; 0x23; 0x5b; 0xe9; 284 + 0x79; 0x96; 0x7c; 0xdb; 0xbc; 0x32; 0xce; 0x96; 0xb5; 0x34; 0x68; 0x94; 0xbf; 0x4f; 0xd7; 0x16; 285 + 0x74; 0x4c; 0x52; 0xf2; 0x04; 0xfb; 0x6a; 0xe6; 0xb9; 0x07; 0x7c; 0x8f; 0x62; 0xdf; 0x13; 0xb7; 286 + 0x3e; 0xd6; 0x85; 0x12; 0x46; 0xfd; 0xb8; 0x2b; 0x30; 0x5e; 0x16; 0x25; 0x8e; 0x2a; 0x20; 0x01; 287 + 0x07; 0xe8; 0x5f; 0x0d; 0x77; 0x08; 0xd5 288 + 289 + ] ; [ 290 + 291 + 0x00; 0x80; 0xbb; 0xbc; 0x2d; 0xca; 0xd8; 0x46; 0x74; 0x90; 0x7c; 0x43; 0xfc; 0xf5; 0x80; 0xe9; 292 + 0xcf; 0xdb; 0xd9; 0x58; 0xa3; 0xf5; 0x68; 0xb4; 0x2d; 0x4b; 0x08; 0xee; 0xd4; 0xeb; 0x0f; 0xb3; 293 + 0x50; 0x4c; 0x6c; 0x03; 0x02; 0x76; 0xe7; 0x10; 0x80; 0x0c; 0x5c; 0xcb; 0xba; 0xa8; 0x92; 0x26; 294 + 0x14; 0xc5; 0xbe; 0xec; 0xa5; 0x65; 0xa5; 0xfd; 0xf1; 0xd2; 0x87; 0xa2; 0xbc; 0x04; 0x9b; 0xe6; 295 + 0x77; 0x80; 0x60; 0xe9; 0x1a; 0x92; 0xa7; 0x57; 0xe3; 0x04; 0x8f; 0x68; 0xb0; 0x76; 0xf7; 0xd3; 296 + 0x6c; 0xc8; 0xf2; 0x9b; 0xa5; 0xdf; 0x81; 0xdc; 0x2c; 0xa7; 0x25; 0xec; 0xe6; 0x62; 0x70; 0xcc; 297 + 0x9a; 0x50; 0x35; 0xd8; 0xce; 0xce; 0xef; 0x9e; 0xa0; 0x27; 0x4a; 0x63; 0xab; 0x1e; 0x58; 0xfa; 298 + 0xfd; 0x49; 0x88; 0xd0; 0xf6; 0x5d; 0x14; 0x67; 0x57; 0xda; 0x07; 0x1d; 0xf0; 0x45; 0xcf; 0xe1; 299 + 0x6b; 0x9b; 0x00; 0x01; 0x02; 0x00; 0x80; 0x4a; 0x2d; 0x33; 0x76; 0x4d; 0x32; 0x70; 0xf1; 0x94; 300 + 0x1a; 0xc1; 0x35; 0x63; 0x97; 0x62; 0xca; 0xcc; 0xd6; 0x2d; 0xfd; 0x23; 0x2d; 0x3a; 0x71; 0x03; 301 + 0xc4; 0x9d; 0x42; 0x93; 0x78; 0x8c; 0x32; 0xc4; 0x8b; 0x0d; 0xad; 0xdd; 0xe2; 0x30; 0x96; 0xf1; 302 + 0xb9; 0xef; 0x16; 0x72; 0x2e; 0x6d; 0x1f; 0xb9; 0x92; 0x5d; 0x17; 0xc5; 0x0f; 0x2b; 0x07; 0xc8; 303 + 0xae; 0xf7; 0x60; 0x3d; 0x53; 0x62; 0x2e; 0xb5; 0xe3; 0x0b; 0x20; 0x67; 0xb1; 0xdf; 0x57; 0x14; 304 + 0x59; 0xff; 0xca; 0xe6; 0x72; 0x5d; 0xd7; 0x1a; 0x98; 0x1e; 0xa1; 0x2b; 0xce; 0xf7; 0x9e; 0xcf; 305 + 0x45; 0x41; 0xa4; 0xa8; 0xdc; 0x98; 0xf7; 0x0d; 0x98; 0xf3; 0x47; 0x7a; 0xe3; 0x25; 0x41; 0x02; 306 + 0x31; 0x26; 0x1f; 0x4d; 0xbb; 0x36; 0xcd; 0xcc; 0x64; 0x74; 0xae; 0xb5; 0x19; 0xd9; 0xa3; 0xd6; 307 + 0x89; 0x6f; 0x9d; 0x02; 0xd4; 0x52; 0xdd 308 + 309 + ] ; [ 310 + 311 + 0x00; 0x80; 0xbb; 0xbc; 0x2d; 0xca; 0xd8; 0x46; 0x74; 0x90; 0x7c; 0x43; 0xfc; 0xf5; 0x80; 0xe9; 312 + 0xcf; 0xdb; 0xd9; 0x58; 0xa3; 0xf5; 0x68; 0xb4; 0x2d; 0x4b; 0x08; 0xee; 0xd4; 0xeb; 0x0f; 0xb3; 313 + 0x50; 0x4c; 0x6c; 0x03; 0x02; 0x76; 0xe7; 0x10; 0x80; 0x0c; 0x5c; 0xcb; 0xba; 0xa8; 0x92; 0x26; 314 + 0x14; 0xc5; 0xbe; 0xec; 0xa5; 0x65; 0xa5; 0xfd; 0xf1; 0xd2; 0x87; 0xa2; 0xbc; 0x04; 0x9b; 0xe6; 315 + 0x77; 0x80; 0x60; 0xe9; 0x1a; 0x92; 0xa7; 0x57; 0xe3; 0x04; 0x8f; 0x68; 0xb0; 0x76; 0xf7; 0xd3; 316 + 0x6c; 0xc8; 0xf2; 0x9b; 0xa5; 0xdf; 0x81; 0xdc; 0x2c; 0xa7; 0x25; 0xec; 0xe6; 0x62; 0x70; 0xcc; 317 + 0x9a; 0x50; 0x35; 0xd8; 0xce; 0xce; 0xef; 0x9e; 0xa0; 0x27; 0x4a; 0x63; 0xab; 0x1e; 0x58; 0xfa; 318 + 0xfd; 0x49; 0x88; 0xd0; 0xf6; 0x5d; 0x14; 0x67; 0x57; 0xda; 0x07; 0x1d; 0xf0; 0x45; 0xcf; 0xe1; 319 + 0x6b; 0x9b; 0x00; 0x01; 0x02; 0x00; 0x80; 0x0c; 0x00; 0xda; 0x79; 0x24; 0x02; 0x33; 0x29; 0xf5; 320 + 0x81; 0xc4; 0x67; 0x5a; 0x03; 0x2b; 0xbf; 0xaf; 0xd6; 0x76; 0xdd; 0x26; 0xdc; 0xd4; 0x38; 0x35; 321 + 0xc1; 0x7f; 0x3a; 0x9e; 0x02; 0x31; 0x73; 0x17; 0xf2; 0x68; 0x5f; 0xd4; 0xf0; 0x6a; 0x97; 0x51; 322 + 0xb2; 0x42; 0xb4; 0x8d; 0x35; 0x89; 0x29; 0x96; 0x27; 0xf7; 0x89; 0x59; 0x9b; 0x93; 0xb0; 0x4f; 323 + 0x85; 0x28; 0xfa; 0x10; 0xe7; 0x15; 0x09; 0x71; 0x10; 0x36; 0x01; 0x60; 0xcf; 0xe0; 0x37; 0xbb; 324 + 0xfd; 0xcd; 0xc3; 0x9e; 0x27; 0xf8; 0xf4; 0x90; 0xcd; 0x87; 0xd9; 0x5c; 0x92; 0x08; 0x44; 0x32; 325 + 0xb5; 0x2b; 0xe2; 0xa5; 0x72; 0xde; 0x97; 0x0c; 0x4f; 0xc7; 0x60; 0x8d; 0xe7; 0xcf; 0x64; 0xba; 326 + 0x7e; 0x0d; 0x0f; 0x91; 0x58; 0x0d; 0x47; 0x6c; 0x3f; 0xb8; 0x4f; 0xb9; 0x02; 0xc5; 0xcc; 0x72; 327 + 0x33; 0x33; 0xde; 0xf2; 0x8f; 0x6b; 0x8c 328 + 329 + ] ; [ 330 + 331 + 0x00; 0x80; 0xbb; 0xbc; 0x2d; 0xca; 0xd8; 0x46; 0x74; 0x90; 0x7c; 0x43; 0xfc; 0xf5; 0x80; 0xe9; 332 + 0xcf; 0xdb; 0xd9; 0x58; 0xa3; 0xf5; 0x68; 0xb4; 0x2d; 0x4b; 0x08; 0xee; 0xd4; 0xeb; 0x0f; 0xb3; 333 + 0x50; 0x4c; 0x6c; 0x03; 0x02; 0x76; 0xe7; 0x10; 0x80; 0x0c; 0x5c; 0xcb; 0xba; 0xa8; 0x92; 0x26; 334 + 0x14; 0xc5; 0xbe; 0xec; 0xa5; 0x65; 0xa5; 0xfd; 0xf1; 0xd2; 0x87; 0xa2; 0xbc; 0x04; 0x9b; 0xe6; 335 + 0x77; 0x80; 0x60; 0xe9; 0x1a; 0x92; 0xa7; 0x57; 0xe3; 0x04; 0x8f; 0x68; 0xb0; 0x76; 0xf7; 0xd3; 336 + 0x6c; 0xc8; 0xf2; 0x9b; 0xa5; 0xdf; 0x81; 0xdc; 0x2c; 0xa7; 0x25; 0xec; 0xe6; 0x62; 0x70; 0xcc; 337 + 0x9a; 0x50; 0x35; 0xd8; 0xce; 0xce; 0xef; 0x9e; 0xa0; 0x27; 0x4a; 0x63; 0xab; 0x1e; 0x58; 0xfa; 338 + 0xfd; 0x49; 0x88; 0xd0; 0xf6; 0x5d; 0x14; 0x67; 0x57; 0xda; 0x07; 0x1d; 0xf0; 0x45; 0xcf; 0xe1; 339 + 0x6b; 0x9b; 0x00; 0x01; 0x02; 0x00; 0x80; 0x7e; 0x8f; 0xc7; 0x38; 0x8a; 0xf8; 0xdd; 0x7a; 0xb2; 340 + 0x0a; 0x07; 0xdd; 0x00; 0xfb; 0x63; 0x58; 0x85; 0xde; 0xc7; 0x6a; 0xe0; 0x0a; 0x51; 0x06; 0x7b; 341 + 0x3e; 0xfd; 0xac; 0xfe; 0xe2; 0x7a; 0xf7; 0x3f; 0xcb; 0xb2; 0xfc; 0x30; 0x45; 0xfa; 0x2b; 0x74; 342 + 0xb7; 0x2f; 0xf5; 0xf9; 0x52; 0xef; 0x93; 0x3f; 0xdb; 0x7e; 0x00; 0xe7; 0xd4; 0xa4; 0x20; 0xbe; 343 + 0x2d; 0x6f; 0xde; 0x28; 0x6c; 0x74; 0x8b; 0x23; 0xc6; 0x14; 0xdc; 0xb9; 0x24; 0xca; 0x87; 0xe0; 344 + 0xe9; 0x5e; 0xb0; 0x4e; 0x55; 0x74; 0x54; 0x4d; 0x8a; 0x21; 0x26; 0x62; 0x28; 0x2a; 0xe6; 0xb1; 345 + 0x29; 0xdc; 0xcd; 0xda; 0x27; 0xc4; 0xcd; 0x8d; 0xd3; 0x47; 0x40; 0x05; 0x1f; 0xbb; 0x80; 0xef; 346 + 0xa0; 0xf4; 0x5a; 0x22; 0x7c; 0x4a; 0xe5; 0xb0; 0x59; 0x68; 0xa5; 0x3e; 0xbb; 0x6f; 0x62; 0x30; 347 + 0x20; 0xc1; 0x43; 0x91; 0xd2; 0x79; 0xf5 348 + 349 + ] ; [ 350 + 351 + 0x00; 0x80; 0xbb; 0xbc; 0x2d; 0xca; 0xd8; 0x46; 0x74; 0x90; 0x7c; 0x43; 0xfc; 0xf5; 0x80; 0xe9; 352 + 0xcf; 0xdb; 0xd9; 0x58; 0xa3; 0xf5; 0x68; 0xb4; 0x2d; 0x4b; 0x08; 0xee; 0xd4; 0xeb; 0x0f; 0xb3; 353 + 0x50; 0x4c; 0x6c; 0x03; 0x02; 0x76; 0xe7; 0x10; 0x80; 0x0c; 0x5c; 0xcb; 0xba; 0xa8; 0x92; 0x26; 354 + 0x14; 0xc5; 0xbe; 0xec; 0xa5; 0x65; 0xa5; 0xfd; 0xf1; 0xd2; 0x87; 0xa2; 0xbc; 0x04; 0x9b; 0xe6; 355 + 0x77; 0x80; 0x60; 0xe9; 0x1a; 0x92; 0xa7; 0x57; 0xe3; 0x04; 0x8f; 0x68; 0xb0; 0x76; 0xf7; 0xd3; 356 + 0x6c; 0xc8; 0xf2; 0x9b; 0xa5; 0xdf; 0x81; 0xdc; 0x2c; 0xa7; 0x25; 0xec; 0xe6; 0x62; 0x70; 0xcc; 357 + 0x9a; 0x50; 0x35; 0xd8; 0xce; 0xce; 0xef; 0x9e; 0xa0; 0x27; 0x4a; 0x63; 0xab; 0x1e; 0x58; 0xfa; 358 + 0xfd; 0x49; 0x88; 0xd0; 0xf6; 0x5d; 0x14; 0x67; 0x57; 0xda; 0x07; 0x1d; 0xf0; 0x45; 0xcf; 0xe1; 359 + 0x6b; 0x9b; 0x00; 0x01; 0x02; 0x00; 0x80; 0x73; 0x47; 0x2a; 0xde; 0x22; 0x94; 0x39; 0x77; 0x46; 360 + 0x25; 0xe2; 0x2d; 0x4f; 0x8d; 0x9e; 0x99; 0x10; 0xa2; 0x1a; 0xd6; 0xf1; 0xe6; 0x25; 0x7f; 0x76; 361 + 0xbe; 0x87; 0xf6; 0xff; 0xce; 0x7d; 0xd7; 0xd2; 0xee; 0xc5; 0x01; 0x0b; 0x14; 0xa1; 0xda; 0x0a; 362 + 0x56; 0x4f; 0xff; 0x8c; 0xdd; 0x84; 0x7c; 0xd8; 0xcc; 0xa8; 0xc1; 0xc3; 0xa1; 0xbf; 0x15; 0x38; 363 + 0xc9; 0x4f; 0xc3; 0x7b; 0xde; 0xf3; 0x37; 0xf3; 0x2f; 0x8e; 0x72; 0x4d; 0xfb; 0x69; 0xc6; 0x4d; 364 + 0xe4; 0x84; 0x46; 0x64; 0xe1; 0xb5; 0x02; 0xe8; 0xf9; 0xbd; 0x94; 0xbf; 0x40; 0x5e; 0x1f; 0xb6; 365 + 0x39; 0xb9; 0x0b; 0x1a; 0x79; 0xf1; 0xa6; 0x3d; 0xee; 0x7a; 0x02; 0xff; 0x62; 0x0d; 0xc6; 0x1e; 366 + 0xfb; 0x5a; 0xcd; 0x36; 0xee; 0x6d; 0x67; 0x5f; 0x81; 0xf4; 0xde; 0x62; 0x15; 0xb6; 0x9a; 0xf3; 367 + 0x24; 0xa2; 0xb3; 0x95; 0xdf; 0x6a; 0xa2 368 + 369 + ] 370 + ] 371 + 372 + let good_dh_param_parser xs _ = 373 + let buf = list_to_cstruct xs in 374 + match Reader.parse_dh_parameters buf with 375 + | Error _ -> assert_failure "dh params parser broken" 376 + | Ok (_, _, rst) -> assert_equal 0 (String.length rst) 377 + 378 + let good_dh_params_tests = 379 + List.mapi 380 + (fun i f -> "Parse good dh_param " ^ string_of_int i >:: good_dh_param_parser f) 381 + good_dhparams 382 + 383 + let bad_dh_param_parser buf _ = 384 + match Reader.parse_dh_parameters buf with 385 + | Error _ -> () 386 + | Ok (_, _, rst) -> 387 + if String.length rst = 0 then 388 + assert_failure "dh params parser broken" 389 + 390 + let bad_dh_params_tests = 391 + let param = list_to_cstruct (List.hd good_dhparams) in 392 + let l = String.length param in 393 + let bad_params = 394 + [ 395 + param ^ String.make 1 '\x00' ; 396 + String.sub param 2 20 ; 397 + String.sub param 0 20 ; 398 + list_to_cstruct [2] ^ param ; 399 + list_to_cstruct [0] ^ param ; 400 + list_to_cstruct [0; 1] ^ param ; 401 + list_to_cstruct [0; 0] ^ param ; 402 + list_to_cstruct [0xff; 0xff] ^ param ; 403 + list_to_cstruct [0; 0xff] ^ param ; 404 + String.sub param 1 (String.length param - 1); 405 + String.sub param 0 (pred l) 406 + ] 407 + in 408 + let lastparam = list_to_cstruct (List.nth good_dhparams 5) in 409 + let l = String.length lastparam in 410 + let more_bad = 411 + [ 412 + String.sub lastparam 0 130 ^ list_to_cstruct [0 ; 5 ; 1] ^ String.sub lastparam 130 (l - 130) ; 413 + String.sub lastparam 0 133 ^ list_to_cstruct [0 ; 5 ; 1] ^ String.sub lastparam 133 (l - 133) 414 + ] 415 + in 416 + List.mapi 417 + (fun i f -> "Parse bad dh_param " ^ string_of_int i >:: bad_dh_param_parser f) 418 + (bad_params @ more_bad) 419 + 420 + let good_digitally_signed_1_2 = [ 421 + [ 422 + 423 + 0x06; 0x01; 0x01; 0x00; 0x30; 0x92; 0xf4; 0x70; 0xb1; 0x02; 0x0a; 0x51; 0xb6; 0x0e; 0x49; 0x1e; 424 + 0x16; 0x6d; 0x9f; 0xb5; 0xfe; 0x73; 0x5e; 0x2f; 0x18; 0xbc; 0xf7; 0x87; 0xab; 0x2c; 0xad; 0x7e; 425 + 0x54; 0x40; 0x99; 0x30; 0xa2; 0x2e; 0x55; 0xe0; 0xf3; 0x05; 0xe1; 0x81; 0x67; 0x78; 0x49; 0x29; 426 + 0xe6; 0x5d; 0x2c; 0x64; 0x57; 0xeb; 0x8c; 0x68; 0x24; 0xe1; 0xba; 0x69; 0x50; 0xc7; 0xda; 0x73; 427 + 0x9a; 0x02; 0xe4; 0xbc; 0xc0; 0x76; 0x65; 0xaf; 0x31; 0x93; 0xbc; 0x2f; 0x5c; 0xdb; 0xa5; 0x1d; 428 + 0x4e; 0xb2; 0x75; 0x0d; 0xb4; 0x22; 0x23; 0x05; 0x5b; 0x8c; 0xa0; 0x14; 0x4c; 0x64; 0xb9; 0x91; 429 + 0xa6; 0x22; 0xc2; 0x49; 0xaa; 0x41; 0xb0; 0x42; 0x04; 0x2a; 0x03; 0x03; 0x1e; 0x62; 0x74; 0x64; 430 + 0x98; 0xaf; 0xcf; 0x9a; 0xd0; 0x22; 0xa8; 0xf3; 0xa5; 0x0a; 0x0d; 0xe9; 0xdc; 0xe2; 0x89; 0xe5; 431 + 0x54; 0xa2; 0x28; 0x25; 0x69; 0x4e; 0xe5; 0xc3; 0xa6; 0x23; 0xd2; 0xeb; 0x67; 0x8a; 0xb8; 0x4a; 432 + 0xac; 0x19; 0x1d; 0x00; 0xa9; 0xec; 0xca; 0xeb; 0xf9; 0x79; 0x2c; 0x7c; 0x6e; 0x31; 0x7f; 0x64; 433 + 0x64; 0xa2; 0xfb; 0x93; 0xc5; 0x91; 0xa2; 0xad; 0x8e; 0x36; 0x07; 0xe8; 0x51; 0x0b; 0x08; 0x36; 434 + 0xb7; 0x78; 0xac; 0x21; 0x3d; 0xc9; 0xfb; 0xae; 0xab; 0xe5; 0xd9; 0x9c; 0xa7; 0xee; 0x5e; 0xcb; 435 + 0xab; 0x57; 0x9d; 0x62; 0x6c; 0x2e; 0xbd; 0x6d; 0x4a; 0xd0; 0x36; 0xb1; 0xa8; 0xf1; 0x22; 0xd8; 436 + 0x97; 0x5c; 0x24; 0xb3; 0x72; 0x55; 0x20; 0x39; 0x29; 0x26; 0x51; 0x3b; 0x9c; 0x48; 0x80; 0x25; 437 + 0xa9; 0xf4; 0xc1; 0xb0; 0x57; 0xd8; 0x3f; 0x54; 0x5e; 0x99; 0x27; 0x36; 0x81; 0xcd; 0x23; 0xf6; 438 + 0xaa; 0x84; 0x98; 0xf8; 0x66; 0x79; 0xe1; 0x16; 0xb9; 0xeb; 0xc6; 0x9a; 0x86; 0x90; 0xa6; 0xa2; 439 + 0x9d; 0x0d; 0x86; 0x32 440 + 441 + ] ; [ 442 + 443 + 0x06; 0x01; 0x01; 0x00; 0x8e; 0x02; 0x51; 0x93; 0x67; 0xe8; 0x68; 0xfe; 0x65; 0x61; 0xda; 0xf0; 444 + 0x25; 0x1a; 0x19; 0x5a; 0x36; 0x42; 0x11; 0xdd; 0x00; 0x2b; 0xf2; 0x38; 0x98; 0xef; 0x94; 0x42; 445 + 0xac; 0x3d; 0x82; 0xc7; 0x85; 0x72; 0xf3; 0xb7; 0x73; 0x4d; 0x6b; 0x64; 0x66; 0x6a; 0x89; 0x6d; 446 + 0x95; 0x67; 0xdb; 0xb7; 0x83; 0x1e; 0xb1; 0x7c; 0xf4; 0xb9; 0x60; 0xbd; 0x91; 0x26; 0xe0; 0x4c; 447 + 0x6c; 0x92; 0xc7; 0xc4; 0x8b; 0xb5; 0x8d; 0xaf; 0xfd; 0xaa; 0xd9; 0xcc; 0x2f; 0xaf; 0x6b; 0x18; 448 + 0xf7; 0x4f; 0xcd; 0x8d; 0x54; 0xe1; 0x70; 0x5c; 0xa9; 0xec; 0x85; 0xd9; 0x7b; 0x5b; 0xa2; 0x9a; 449 + 0x55; 0xc2; 0x5a; 0x87; 0xd4; 0xbe; 0x49; 0xf2; 0x03; 0x95; 0x50; 0x5f; 0x62; 0xa7; 0x4d; 0x13; 450 + 0x29; 0xae; 0x19; 0xcc; 0x2e; 0x21; 0x9b; 0x36; 0x60; 0xc4; 0xd7; 0x5a; 0x8f; 0xe2; 0x67; 0x73; 451 + 0x22; 0x85; 0x66; 0xbb; 0x00; 0x00; 0x97; 0x10; 0xbc; 0x19; 0x16; 0xce; 0x14; 0x8e; 0x27; 0x1e; 452 + 0x79; 0x3e; 0xbd; 0xc3; 0xc9; 0x5c; 0xc2; 0xbf; 0x7b; 0x83; 0xba; 0x00; 0x20; 0x18; 0x54; 0x0b; 453 + 0x09; 0x11; 0xb3; 0x0b; 0x75; 0x7d; 0xf6; 0xc7; 0x80; 0x76; 0x25; 0x3c; 0x3b; 0xdb; 0x67; 0xc5; 454 + 0xe7; 0x77; 0x0a; 0xe1; 0xbf; 0xd9; 0xc2; 0x6c; 0xc2; 0x3f; 0x37; 0x4b; 0xcf; 0x6c; 0x64; 0x53; 455 + 0x4a; 0xf3; 0x81; 0x6d; 0xd8; 0x13; 0xce; 0xb4; 0x84; 0x42; 0x7b; 0x73; 0x85; 0x11; 0xaa; 0x0e; 456 + 0x39; 0xd8; 0x99; 0x76; 0x5e; 0xe8; 0xe0; 0xbc; 0x08; 0xe6; 0x7b; 0xba; 0xc9; 0x6e; 0xdd; 0x63; 457 + 0x38; 0xca; 0x5b; 0x8b; 0x74; 0xed; 0x52; 0x04; 0xe3; 0x64; 0xe6; 0xdc; 0xfa; 0x1d; 0x46; 0xca; 458 + 0x5d; 0xf8; 0x18; 0x3e; 0xa7; 0x39; 0x7e; 0x19; 0xb9; 0x2f; 0x87; 0x5b; 0x2a; 0x55; 0x85; 0xe5; 459 + 0x9e; 0x92; 0x6b; 0x62 460 + 461 + ] ; [ 462 + 463 + 0x06; 0x01; 0x01; 0x00; 0x2b; 0x5b; 0x89; 0xfa; 0x67; 0x4b; 0x58; 0x45; 0xd4; 0x8f; 0x22; 0x4b; 464 + 0x53; 0x3b; 0x92; 0x2b; 0x37; 0x18; 0xcd; 0x05; 0xda; 0xb5; 0x85; 0x11; 0x23; 0x12; 0xdc; 0x18; 465 + 0xb5; 0x9f; 0xb0; 0x45; 0x16; 0xf3; 0x1c; 0xf8; 0x93; 0xb8; 0x8c; 0x37; 0xd5; 0x60; 0x68; 0xee; 466 + 0x75; 0x53; 0xa9; 0x5f; 0x22; 0x4e; 0x01; 0x2b; 0xb3; 0xb6; 0x3e; 0x29; 0xba; 0x2c; 0xef; 0xa8; 467 + 0x3f; 0x07; 0xa3; 0xfb; 0x91; 0xf8; 0x2c; 0x8d; 0x23; 0xe3; 0x8d; 0x26; 0x26; 0x11; 0xa4; 0xd9; 468 + 0xa0; 0xa4; 0x10; 0x11; 0x40; 0x1a; 0xad; 0xc3; 0xa4; 0x99; 0x5a; 0xae; 0x97; 0xae; 0x9b; 0x39; 469 + 0xdc; 0x98; 0xb3; 0x34; 0xe7; 0x08; 0xb4; 0x5f; 0xae; 0xa1; 0xf7; 0x79; 0x92; 0xd3; 0x8d; 0x23; 470 + 0x47; 0xa4; 0x8d; 0xa8; 0x1a; 0x4a; 0xae; 0x10; 0xd7; 0xf8; 0xe0; 0x7a; 0xf4; 0x52; 0x5a; 0xb0; 471 + 0xc3; 0x6f; 0x5a; 0x8a; 0x94; 0x75; 0xbf; 0x27; 0xc1; 0xbb; 0xb0; 0x5c; 0x66; 0x66; 0x60; 0x0d; 472 + 0xdd; 0xa8; 0xcf; 0x1b; 0xee; 0x6f; 0x33; 0x63; 0xec; 0xaa; 0x16; 0x15; 0x3a; 0xcc; 0x72; 0x6f; 473 + 0x9e; 0xc1; 0x06; 0xf3; 0x45; 0xec; 0x7f; 0x6b; 0x17; 0xab; 0xce; 0x63; 0x15; 0x8c; 0x0e; 0x61; 474 + 0x98; 0xd9; 0xc4; 0x68; 0xba; 0x56; 0x88; 0x0a; 0x46; 0xcc; 0x0c; 0xd9; 0x09; 0xea; 0x8f; 0xdb; 475 + 0x28; 0x35; 0x16; 0xa2; 0x5d; 0xfb; 0xc2; 0x93; 0xf3; 0xa5; 0x53; 0xe4; 0x94; 0xda; 0x45; 0xa9; 476 + 0x81; 0x0c; 0x43; 0x45; 0x67; 0xef; 0x70; 0x4a; 0x06; 0x67; 0xb1; 0xb6; 0x30; 0x19; 0x16; 0xb1; 477 + 0xeb; 0x28; 0x3c; 0x8b; 0x13; 0x94; 0x1a; 0x79; 0x8c; 0x92; 0x7b; 0xe0; 0xfb; 0xea; 0xd1; 0xfc; 478 + 0x50; 0xf8; 0xb7; 0x86; 0x76; 0xa1; 0x69; 0x81; 0x3e; 0xb1; 0x88; 0xf5; 0xa7; 0x05; 0xe9; 0xe1; 479 + 0xd1; 0x9e; 0xbc; 0x15 480 + 481 + ] ; [ 482 + 483 + 0x06; 0x01; 0x01; 0x00; 0x6c; 0x1b; 0xe8; 0x31; 0x7b; 0xab; 0x2b; 0x5f; 0xa0; 0x9f; 0x6d; 0x73; 484 + 0x43; 0x83; 0x67; 0xd2; 0x85; 0xae; 0x85; 0x56; 0x65; 0x6a; 0xf9; 0x82; 0xc0; 0x29; 0x48; 0x28; 485 + 0x9d; 0xd9; 0x2a; 0x23; 0xea; 0x8d; 0x0c; 0xc2; 0x9e; 0x8f; 0x84; 0xb6; 0x74; 0x5d; 0xaf; 0xdf; 486 + 0x0a; 0x39; 0x5f; 0x4a; 0x2c; 0xa0; 0xb8; 0x02; 0x20; 0xa6; 0x33; 0x3f; 0x22; 0x2b; 0x38; 0x49; 487 + 0x5f; 0x21; 0xea; 0x62; 0x1a; 0x73; 0xe4; 0x0a; 0x1f; 0xf5; 0xe0; 0x89; 0x8c; 0xb3; 0xdd; 0xf4; 488 + 0xef; 0xc8; 0x35; 0x8f; 0x60; 0xa2; 0x4c; 0x95; 0xf7; 0xcb; 0x8e; 0x1f; 0xf0; 0x15; 0xf4; 0x22; 489 + 0x01; 0x97; 0xb0; 0x59; 0x4e; 0x59; 0x40; 0x7c; 0x43; 0xdf; 0x1c; 0x35; 0x5f; 0x8d; 0xde; 0x26; 490 + 0x77; 0x0d; 0x47; 0xec; 0x84; 0x30; 0x7f; 0x0e; 0xf3; 0x17; 0x3b; 0x26; 0x8b; 0x35; 0x9d; 0xe2; 491 + 0x02; 0x49; 0x82; 0xa4; 0x4e; 0x0d; 0xb2; 0xd9; 0x5f; 0x83; 0x55; 0x8d; 0x56; 0xb2; 0x7e; 0x33; 492 + 0x11; 0x9f; 0x50; 0xfb; 0xf3; 0xaf; 0xa6; 0x96; 0x90; 0x52; 0x76; 0xea; 0xbd; 0x03; 0xde; 0x5c; 493 + 0x3a; 0xd7; 0x4f; 0x1c; 0x89; 0xe6; 0xb0; 0xa3; 0x39; 0x8a; 0xb1; 0x70; 0xb9; 0x1f; 0x2f; 0x25; 494 + 0x03; 0xe5; 0xd6; 0x87; 0x36; 0x62; 0xea; 0x4a; 0x8a; 0x60; 0xb5; 0x83; 0x20; 0x62; 0xd5; 0x58; 495 + 0x7e; 0x94; 0x19; 0x42; 0x4d; 0xc7; 0x48; 0xb2; 0xfb; 0xed; 0xfb; 0xd1; 0xc4; 0xfe; 0x7f; 0x48; 496 + 0xf9; 0xe2; 0xd4; 0x15; 0xd1; 0x2c; 0xe1; 0x73; 0x76; 0x77; 0xbf; 0x0c; 0x5a; 0xc3; 0x8b; 0xc2; 497 + 0x6a; 0xd7; 0x58; 0xce; 0xeb; 0x96; 0x58; 0x55; 0xfb; 0x35; 0x5a; 0x8d; 0x82; 0xaa; 0x2e; 0x7d; 498 + 0x0e; 0xd3; 0x8d; 0xb9; 0x6a; 0xfe; 0x02; 0xc3; 0xbc; 0xd2; 0x43; 0xe9; 0x4e; 0x72; 0xe6; 0xbd; 499 + 0xd2; 0x49; 0x63; 0xc5 500 + 501 + ] ; [ 502 + 503 + 0x06; 0x01; 0x01; 0x00; 0x23; 0x8d; 0x01; 0xf7; 0xce; 0xe3; 0xe9; 0xf8; 0xb4; 0x43; 0x5a; 0x48; 504 + 0x4c; 0x98; 0x45; 0x57; 0x45; 0x7a; 0x70; 0x6f; 0x02; 0xf9; 0x3e; 0x18; 0x16; 0x32; 0xce; 0x48; 505 + 0x49; 0x3d; 0x1b; 0xed; 0xbd; 0x96; 0x73; 0xb7; 0xb1; 0x26; 0xdf; 0x07; 0x6c; 0x2a; 0xd0; 0xc4; 506 + 0xc9; 0x7d; 0x79; 0xcc; 0x06; 0xb4; 0x9a; 0x56; 0x17; 0x43; 0xe5; 0x0d; 0xe6; 0x69; 0xd1; 0xbb; 507 + 0xe5; 0xf5; 0xc7; 0x9a; 0x2e; 0xed; 0xec; 0x97; 0xc9; 0x53; 0xb0; 0xab; 0xc6; 0x37; 0x99; 0x2f; 508 + 0xbc; 0xe5; 0x9b; 0xd7; 0xa2; 0xeb; 0xd8; 0x88; 0x29; 0xcf; 0x6f; 0x35; 0x64; 0xd0; 0x40; 0xed; 509 + 0xdd; 0xcd; 0x12; 0x9a; 0x93; 0xb0; 0x6c; 0xde; 0x75; 0x89; 0x5b; 0x19; 0x7b; 0xbb; 0xe7; 0x4f; 510 + 0xcf; 0x6f; 0x87; 0x85; 0x8a; 0xb8; 0xb3; 0x1e; 0xd2; 0xc3; 0x60; 0x51; 0x2c; 0x5b; 0xeb; 0xe3; 511 + 0x77; 0x40; 0x84; 0x75; 0x4f; 0x97; 0x1a; 0x55; 0x67; 0xf6; 0x75; 0x5b; 0xec; 0x61; 0x96; 0x30; 512 + 0x0f; 0x41; 0xc4; 0x02; 0x63; 0x05; 0x52; 0xc8; 0x76; 0x2a; 0x0b; 0x23; 0x6e; 0x97; 0x1f; 0x16; 513 + 0xb6; 0x68; 0x92; 0xc6; 0x2f; 0x9b; 0x1c; 0xe2; 0x2f; 0xf6; 0x02; 0x90; 0x1a; 0x51; 0xa7; 0x49; 514 + 0x43; 0x41; 0x31; 0x22; 0x3f; 0x9a; 0xd1; 0xe7; 0xd0; 0x6b; 0xe4; 0x82; 0x1f; 0xbd; 0x93; 0xca; 515 + 0xaf; 0x5d; 0xf5; 0x05; 0xf3; 0x9a; 0xb8; 0x3d; 0x19; 0x21; 0x8d; 0x0b; 0x20; 0x00; 0x5a; 0x21; 516 + 0x5f; 0x8e; 0x1a; 0x77; 0xd0; 0x70; 0xfb; 0x8c; 0x98; 0x9d; 0x63; 0xb3; 0x9a; 0x6a; 0x3f; 0xc3; 517 + 0x89; 0x43; 0xfe; 0x1c; 0xa7; 0x6f; 0xb6; 0xd6; 0x1f; 0xa9; 0x3e; 0x6c; 0xe2; 0x7a; 0x8e; 0x31; 518 + 0xbc; 0x8f; 0x4e; 0xe4; 0xc0; 0x36; 0x8d; 0x72; 0x01; 0xf4; 0x65; 0x71; 0xff; 0x16; 0xa6; 0xc7; 519 + 0x0a; 0x59; 0xf1; 0x18 520 + 521 + ] 522 + ] 523 + 524 + let good_digitally_signed_1_2_parser xs _ = 525 + let buf = list_to_cstruct xs in 526 + match Reader.parse_digitally_signed_1_2 buf with 527 + | Error _ -> assert_failure "digitally signed 1.2 parser broken" 528 + | Ok _ -> () 529 + 530 + let good_digitally_signed_1_2_tests = 531 + List.mapi 532 + (fun i f -> "Parse good digitally signed 1_2 " ^ string_of_int i >:: good_digitally_signed_1_2_parser f) 533 + good_digitally_signed_1_2 534 + 535 + let bad_dss_1_2 = 536 + let ds = list_to_cstruct (List.hd good_digitally_signed_1_2) in 537 + let l = String.length ds in 538 + [ 539 + String.sub ds 2 20 ; 540 + String.sub ds 0 20 ; 541 + list_to_cstruct [2] ^ ds ; 542 + list_to_cstruct [0] ^ ds ; 543 + list_to_cstruct [0; 1] ^ ds ; 544 + list_to_cstruct [0; 0] ^ ds ; 545 + list_to_cstruct [0xff; 0xff] ^ ds ; 546 + list_to_cstruct [0; 0xff] ^ ds ; 547 + String.sub ds 2 (String.length ds - 2) ; 548 + String.sub ds 0 (pred l) ; 549 + list_to_cstruct [7] ^ String.sub ds 1 (String.length ds - 1) ; 550 + list_to_cstruct [8] ^ String.sub ds 1 (String.length ds - 1) ; 551 + list_to_cstruct [1 ; 7] ^ String.sub ds 2 (String.length ds - 2) ; 552 + list_to_cstruct [7 ; 2] ^ String.sub ds 2 (String.length ds - 2) ; 553 + list_to_cstruct [1 ; 1 ; 1; 0xff] ^ String.sub ds 4 (String.length ds - 4) ; 554 + list_to_cstruct [1 ; 1 ; 0xff ; 0] ^ String.sub ds 4 (String.length ds - 4) ; 555 + ds ^ String.make 1 '\x00' 556 + ] 557 + 558 + let bad_digitally_signed_1_2_parser buf _ = 559 + match Reader.parse_digitally_signed_1_2 buf with 560 + | Error _ -> () 561 + | Ok _ -> assert_failure "digitally signed 1.2 parser broken" 562 + 563 + let bad_digitally_signed_1_2_tests = 564 + List.mapi 565 + (fun i f -> "Parse bad digitally signed 1.2 " ^ string_of_int i >:: bad_digitally_signed_1_2_parser f) 566 + bad_dss_1_2 567 + 568 + let good_digitally_signed_parser xs _ = 569 + let buf = 570 + let b = list_to_cstruct xs in 571 + String.sub b 2 (String.length b - 2) 572 + in 573 + match Reader.parse_digitally_signed buf with 574 + | Error _ -> assert_failure "digitally signed parser broken" 575 + | Ok _ -> () 576 + 577 + let good_digitally_signed_tests = 578 + List.mapi 579 + (fun i f -> "Parse good digitally signed " ^ string_of_int i >:: good_digitally_signed_parser f) 580 + good_digitally_signed_1_2 581 + 582 + let bad_dss = 583 + let ds = 584 + let buf = list_to_cstruct (List.hd good_digitally_signed_1_2) in 585 + String.sub buf 2 (String.length buf - 2) in 586 + let l = String.length ds in 587 + [ 588 + list_to_cstruct [0xff ; 0xff] ^ ds ; 589 + list_to_cstruct [0xff ; 0xff] ^ String.sub ds 2 (String.length ds - 2); 590 + String.sub ds 2 (String.length ds - 2) ; 591 + String.sub ds 0 (pred l) ; 592 + list_to_cstruct [1; 1] ^ String.sub ds 2 (String.length ds - 2); 593 + ds ^ String.make 1 '\x00' 594 + ] 595 + 596 + let bad_digitally_signed_parser buf _ = 597 + match Reader.parse_digitally_signed buf with 598 + | Error _ -> () 599 + | Ok _ -> assert_failure "digitally signed parser broken" 600 + 601 + let bad_digitally_signed_tests = 602 + List.mapi 603 + (fun i f -> "Parse bad digitally signed " ^ string_of_int i >:: bad_digitally_signed_parser f) 604 + bad_dss 605 + 606 + let good_handshake_hdrs = 607 + let data = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11 ] in 608 + let empty = "" in 609 + [ 610 + ([0; 0; 0], (None, list_to_cstruct [0;0;0])) ; 611 + ([0; 0; 0; 0], (Some (list_to_cstruct [0;0;0;0]), empty)) ; 612 + ([0; 0; 0; 0xFF], (None, list_to_cstruct [0;0;0;255])) ; 613 + ([0; 0; 1; 0], (None, list_to_cstruct [0;0;1;0])) ; 614 + ([16; 0; 0; 12] @ data , (Some (list_to_cstruct ([16;0;0;12] @ data)), empty)) ; 615 + ([16; 0; 0; 14] @ data , (None, list_to_cstruct ([16;0;0;14] @ data))) 616 + ] 617 + 618 + let good_handshake_hdr_parser (xs, (hs, rest)) _ = 619 + let buf = list_to_cstruct xs in 620 + match Reader.parse_handshake_frame buf, hs with 621 + | (Some x, rest'), Some y -> 622 + assert_cs_eq y x ; 623 + assert_cs_eq rest rest' ; 624 + | (None, rest'), None -> 625 + assert_cs_eq rest rest' ; 626 + | _ -> assert_failure "handshake_frame parser broken" 627 + 628 + let good_handshake_hdr_tests = 629 + List.mapi 630 + (fun i f -> "Parse good handshake header " ^ string_of_int i >:: good_handshake_hdr_parser f) 631 + good_handshake_hdrs 632 + 633 + (* 1byte type ; 3 byte length ; data *) 634 + let good_handshakes_no_data = [ 635 + ([0; 0; 0; 0] , Core.HelloRequest) ; 636 + ([14; 0; 0; 0] , Core.ServerHelloDone) ; 637 + ] 638 + 639 + let good_handshake_no_data_parser (xs, res) _ = 640 + let buf = list_to_cstruct xs in 641 + match Reader.parse_handshake buf with 642 + | Ok r -> assert_equal res r 643 + | Error _ -> assert_failure "handshake no data parser failed" 644 + 645 + let good_handshake_no_data_tests = 646 + List.mapi 647 + (fun i f -> "Parse good handshake " ^ string_of_int i >:: good_handshake_no_data_parser f) 648 + good_handshakes_no_data 649 + 650 + let bad_handshakes_no_data = [ 651 + [0; 0; 0; 3] ; 652 + [14; 0; 0; 5] ; 653 + [245; 0; 0; 0] ; 654 + [0; 0; 0; 3; 0; 0; 0] ; 655 + [14; 0; 0; 5; 0; 0; 0; 0; 0] 656 + ] 657 + 658 + let bad_handshake_no_data_parser xs _ = 659 + let buf = list_to_cstruct xs in 660 + match Reader.parse_handshake buf with 661 + | Ok _ -> assert_failure "bad handshake no data parser failed" 662 + | Error _ -> () 663 + 664 + let bad_handshake_no_data_tests = 665 + List.mapi 666 + (fun i f -> "Parse bad handshake (no data) " ^ string_of_int i >:: bad_handshake_no_data_parser f) 667 + bad_handshakes_no_data 668 + 669 + let good_handshake_cstruct_data = 670 + let data = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11 ] in 671 + let data_cs = list_to_cstruct data in 672 + let gh1 = list_to_cstruct [ 673 + 0x30; 0x82; 0x05; 0xe0; 0x30; 0x82; 674 + 0x04; 0xc8; 0xa0; 0x03; 0x02; 0x01; 0x02; 0x02; 0x10; 0x0c; 0x00; 0x93; 0x10; 0xd2; 0x06; 0xdb; 675 + 0xe3; 0x37; 0x55; 0x35; 0x80; 0x11; 0x8d; 0xdc; 0x87; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 676 + 0x86; 0xf7; 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x30; 0x75; 0x31; 0x0b; 0x30; 0x09; 0x06; 0x03; 677 + 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x15; 0x30; 0x13; 0x06; 0x03; 0x55; 0x04; 0x0a; 678 + 0x13; 0x0c; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x20; 0x49; 0x6e; 0x63; 0x31; 0x19; 679 + 0x30; 0x17; 0x06; 0x03; 0x55; 0x04; 0x0b; 0x13; 0x10; 0x77; 0x77; 0x77; 0x2e; 0x64; 0x69; 0x67; 680 + 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x31; 0x34; 0x30; 0x32; 0x06; 0x03; 0x55; 681 + 0x04; 0x03; 0x13; 0x2b; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x20; 0x53; 0x48; 0x41; 682 + 0x32; 0x20; 0x45; 0x78; 0x74; 0x65; 0x6e; 0x64; 0x65; 0x64; 0x20; 0x56; 0x61; 0x6c; 0x69; 0x64; 683 + 0x61; 0x74; 0x69; 0x6f; 0x6e; 0x20; 0x53; 0x65; 0x72; 0x76; 0x65; 0x72; 0x20; 0x43; 0x41; 0x30; 684 + 0x1e; 0x17; 0x0d; 0x31; 0x34; 0x30; 0x34; 0x30; 0x38; 0x30; 0x30; 0x30; 0x30; 0x30; 0x30; 0x5a; 685 + 0x17; 0x0d; 0x31; 0x36; 0x30; 0x34; 0x31; 0x32; 0x31; 0x32; 0x30; 0x30; 0x30; 0x30; 0x5a; 0x30; 686 + 0x81; 0xf0; 0x31; 0x1d; 0x30; 0x1b; 0x06; 0x03; 0x55; 0x04; 0x0f; 0x0c; 0x14; 0x50; 0x72; 0x69; 687 + 0x76; 0x61; 0x74; 0x65; 0x20; 0x4f; 0x72; 0x67; 0x61; 0x6e; 0x69; 0x7a; 0x61; 0x74; 0x69; 0x6f; 688 + 0x6e; 0x31; 0x13; 0x30; 0x11; 0x06; 0x0b; 0x2b; 0x06; 0x01; 0x04; 0x01; 0x82; 0x37; 0x3c; 0x02; 689 + 0x01; 0x03; 0x13; 0x02; 0x55; 0x53; 0x31; 0x19; 0x30; 0x17; 0x06; 0x0b; 0x2b; 0x06; 0x01; 0x04; 690 + 0x01; 0x82; 0x37; 0x3c; 0x02; 0x01; 0x02; 0x13; 0x08; 0x44; 0x65; 0x6c; 0x61; 0x77; 0x61; 0x72; 691 + 0x65; 0x31; 0x10; 0x30; 0x0e; 0x06; 0x03; 0x55; 0x04; 0x05; 0x13; 0x07; 0x35; 0x31; 0x35; 0x37; 692 + 0x35; 0x35; 0x30; 0x31; 0x17; 0x30; 0x15; 0x06; 0x03; 0x55; 0x04; 0x09; 0x13; 0x0e; 0x35; 0x34; 693 + 0x38; 0x20; 0x34; 0x74; 0x68; 0x20; 0x53; 0x74; 0x72; 0x65; 0x65; 0x74; 0x31; 0x0e; 0x30; 0x0c; 694 + 0x06; 0x03; 0x55; 0x04; 0x11; 0x13; 0x05; 0x39; 0x34; 0x31; 0x30; 0x37; 0x31; 0x0b; 0x30; 0x09; 695 + 0x06; 0x03; 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x13; 0x30; 0x11; 0x06; 0x03; 0x55; 696 + 0x04; 0x08; 0x13; 0x0a; 0x43; 0x61; 0x6c; 0x69; 0x66; 0x6f; 0x72; 0x6e; 0x69; 0x61; 0x31; 0x16; 697 + 0x30; 0x14; 0x06; 0x03; 0x55; 0x04; 0x07; 0x13; 0x0d; 0x53; 0x61; 0x6e; 0x20; 0x46; 0x72; 0x61; 698 + 0x6e; 0x63; 0x69; 0x73; 0x63; 0x6f; 0x31; 0x15; 0x30; 0x13; 0x06; 0x03; 0x55; 0x04; 0x0a; 0x13; 699 + 0x0c; 0x47; 0x69; 0x74; 0x48; 0x75; 0x62; 0x2c; 0x20; 0x49; 0x6e; 0x63; 0x2e; 0x31; 0x13; 0x30; 700 + 0x11; 0x06; 0x03; 0x55; 0x04; 0x03; 0x13; 0x0a; 0x67; 0x69; 0x74; 0x68; 0x75; 0x62; 0x2e; 0x63; 701 + 0x6f; 0x6d; 0x30; 0x82; 0x01; 0x22; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 0xf7; 0x0d; 702 + 0x01; 0x01; 0x01; 0x05; 0x00; 0x03; 0x82; 0x01; 0x0f; 0x00; 0x30; 0x82; 0x01; 0x0a; 0x02; 0x82; 703 + 0x01; 0x01; 0x00; 0xb1; 0xd4; 0xdc; 0x3c; 0xaf; 0xfd; 0xf3; 0x4e; 0xed; 0xc1; 0x67; 0xad; 0xe6; 704 + 0xcb; 0x22; 0xe8; 0xb7; 0xe2; 0xab; 0x28; 0xf2; 0xf7; 0xdc; 0x62; 0x70; 0x08; 0xd1; 0x0c; 0xaf; 705 + 0xd6; 0x16; 0x6a; 0x21; 0xb0; 0x36; 0x4b; 0x17; 0x0d; 0x36; 0x63; 0x04; 0xae; 0xbf; 0xea; 0x20; 706 + 0x51; 0x95; 0x65; 0x66; 0xf2; 0xbf; 0xb9; 0x4d; 0xa4; 0x0c; 0x29; 0xeb; 0xf5; 0x15; 0xb1; 0xe8; 707 + 0x35; 0xb3; 0x70; 0x10; 0x94; 0xd5; 0x1b; 0x59; 0xb4; 0x26; 0x0f; 0xd6; 0x83; 0x57; 0x59; 0x9d; 708 + 0xe1; 0x7c; 0x09; 0xdd; 0xe0; 0x13; 0xca; 0x4d; 0x6f; 0x43; 0x9b; 0xcd; 0xcf; 0x87; 0x3a; 0x15; 709 + 0xa7; 0x85; 0xdd; 0x66; 0x83; 0xed; 0x93; 0x0c; 0xfe; 0x2b; 0x6d; 0x38; 0x1c; 0x79; 0x88; 0x90; 710 + 0xcf; 0xad; 0x58; 0x18; 0x2d; 0x51; 0xd1; 0xc2; 0xa3; 0xf2; 0x47; 0x8c; 0x6f; 0x38; 0x09; 0xb9; 711 + 0xb8; 0xef; 0x4c; 0x93; 0x0b; 0xcb; 0x83; 0x94; 0x87; 0xea; 0xe0; 0xa3; 0xb5; 0xd9; 0x7b; 0x9b; 712 + 0x6b; 0x0f; 0x43; 0xf9; 0xca; 0xee; 0x80; 0x0d; 0x28; 0xa7; 0x76; 0xf1; 0x25; 0xf4; 0xc1; 0x35; 713 + 0x3c; 0xf6; 0x74; 0xad; 0xde; 0x6a; 0x33; 0x82; 0x7b; 0xdc; 0xfd; 0x4b; 0x76; 0xa7; 0xc2; 0xee; 714 + 0xf2; 0x6a; 0xbf; 0xa9; 0x24; 0xa6; 0x5f; 0xe7; 0x2e; 0x7c; 0x0e; 0xdb; 0xc3; 0x74; 0x73; 0xfa; 715 + 0x7e; 0xc6; 0xd8; 0xcf; 0x60; 0xeb; 0x36; 0x56; 0x21; 0xb6; 0xc1; 0x8a; 0xb8; 0x24; 0x82; 0x4d; 716 + 0x78; 0x24; 0xba; 0xe9; 0x1d; 0xa1; 0x8a; 0xa7; 0x87; 0xbe; 0x66; 0x25; 0x69; 0xbf; 0xbe; 0x3b; 717 + 0x72; 0x6e; 0x4f; 0xe0; 0xe4; 0x85; 0x25; 0x08; 0xb1; 0x91; 0x89; 0xb8; 0xd6; 0x74; 0x65; 0x76; 718 + 0x9b; 0x2c; 0x4f; 0x62; 0x1f; 0xa1; 0xfa; 0x3a; 0xbe; 0x9c; 0x24; 0xbf; 0x9f; 0xca; 0xb0; 0xc5; 719 + 0xc0; 0x67; 0x8d; 0x02; 0x03; 0x01; 0x00; 0x01; 0xa3; 0x82; 0x01; 0xee; 0x30; 0x82; 0x01; 0xea; 720 + 0x30; 0x1f; 0x06; 0x03; 0x55; 0x1d; 0x23; 0x04; 0x18; 0x30; 0x16; 0x80; 0x14; 0x3d; 0xd3; 0x50; 721 + 0xa5; 0xd6; 0xa0; 0xad; 0xee; 0xf3; 0x4a; 0x60; 0x0a; 0x65; 0xd3; 0x21; 0xd4; 0xf8; 0xf8; 0xd6; 722 + 0x0f; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x0e; 0x04; 0x16; 0x04; 0x14; 0x6a; 0x43; 0x90; 0x7d; 723 + 0x3b; 0x98; 0x14; 0x72; 0x52; 0x95; 0x3a; 0xaa; 0x28; 0x0a; 0x43; 0xf8; 0x51; 0x7e; 0xd3; 0xa6; 724 + 0x30; 0x25; 0x06; 0x03; 0x55; 0x1d; 0x11; 0x04; 0x1e; 0x30; 0x1c; 0x82; 0x0a; 0x67; 0x69; 0x74; 725 + 0x68; 0x75; 0x62; 0x2e; 0x63; 0x6f; 0x6d; 0x82; 0x0e; 0x77; 0x77; 0x77; 0x2e; 0x67; 0x69; 0x74; 726 + 0x68; 0x75; 0x62; 0x2e; 0x63; 0x6f; 0x6d; 0x30; 0x0e; 0x06; 0x03; 0x55; 0x1d; 0x0f; 0x01; 0x01; 727 + 0xff; 0x04; 0x04; 0x03; 0x02; 0x05; 0xa0; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x25; 0x04; 0x16; 728 + 0x30; 0x14; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x03; 0x01; 0x06; 0x08; 0x2b; 0x06; 729 + 0x01; 0x05; 0x05; 0x07; 0x03; 0x02; 0x30; 0x75; 0x06; 0x03; 0x55; 0x1d; 0x1f; 0x04; 0x6e; 0x30; 730 + 0x6c; 0x30; 0x34; 0xa0; 0x32; 0xa0; 0x30; 0x86; 0x2e; 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 731 + 0x63; 0x72; 0x6c; 0x33; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 732 + 0x6d; 0x2f; 0x73; 0x68; 0x61; 0x32; 0x2d; 0x65; 0x76; 0x2d; 0x73; 0x65; 0x72; 0x76; 0x65; 0x72; 733 + 0x2d; 0x67; 0x31; 0x2e; 0x63; 0x72; 0x6c; 0x30; 0x34; 0xa0; 0x32; 0xa0; 0x30; 0x86; 0x2e; 0x68; 734 + 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x63; 0x72; 0x6c; 0x34; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 735 + 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x2f; 0x73; 0x68; 0x61; 0x32; 0x2d; 0x65; 0x76; 0x2d; 736 + 0x73; 0x65; 0x72; 0x76; 0x65; 0x72; 0x2d; 0x67; 0x31; 0x2e; 0x63; 0x72; 0x6c; 0x30; 0x42; 0x06; 737 + 0x03; 0x55; 0x1d; 0x20; 0x04; 0x3b; 0x30; 0x39; 0x30; 0x37; 0x06; 0x09; 0x60; 0x86; 0x48; 0x01; 738 + 0x86; 0xfd; 0x6c; 0x02; 0x01; 0x30; 0x2a; 0x30; 0x28; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 739 + 0x07; 0x02; 0x01; 0x16; 0x1c; 0x68; 0x74; 0x74; 0x70; 0x73; 0x3a; 0x2f; 0x2f; 0x77; 0x77; 0x77; 740 + 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x2f; 0x43; 0x50; 741 + 0x53; 0x30; 0x81; 0x88; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x01; 0x01; 0x04; 0x7c; 742 + 0x30; 0x7a; 0x30; 0x24; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x30; 0x01; 0x86; 0x18; 743 + 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x6f; 0x63; 0x73; 0x70; 0x2e; 0x64; 0x69; 0x67; 0x69; 744 + 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x30; 0x52; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 745 + 0x05; 0x07; 0x30; 0x02; 0x86; 0x46; 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x63; 0x61; 0x63; 746 + 0x65; 0x72; 0x74; 0x73; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 747 + 0x6d; 0x2f; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x53; 0x48; 0x41; 0x32; 0x45; 0x78; 748 + 0x74; 0x65; 0x6e; 0x64; 0x65; 0x64; 0x56; 0x61; 0x6c; 0x69; 0x64; 0x61; 0x74; 0x69; 0x6f; 0x6e; 749 + 0x53; 0x65; 0x72; 0x76; 0x65; 0x72; 0x43; 0x41; 0x2e; 0x63; 0x72; 0x74; 0x30; 0x0c; 0x06; 0x03; 750 + 0x55; 0x1d; 0x13; 0x01; 0x01; 0xff; 0x04; 0x02; 0x30; 0x00; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 751 + 0x48; 0x86; 0xf7; 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x03; 0x82; 0x01; 0x01; 0x00; 0x6f; 0xe7; 752 + 0x6d; 0xcb; 0x82; 0xf3; 0xef; 0x90; 0x87; 0x09; 0xd7; 0x0f; 0x15; 0x22; 0x2c; 0x8c; 0xfe; 0xd3; 753 + 0xab; 0x1c; 0x8a; 0x96; 0xdb; 0x5d; 0x12; 0x5d; 0xd1; 0x78; 0xc0; 0x31; 0xb0; 0xff; 0x45; 0xc8; 754 + 0x89; 0xf7; 0x08; 0x98; 0x52; 0x17; 0x1f; 0x4c; 0x4b; 0x20; 0x64; 0x6a; 0x6d; 0xdb; 0x50; 0xd7; 755 + 0x10; 0xbe; 0x7e; 0xab; 0xfe; 0x2f; 0x80; 0xd8; 0xa9; 0x4a; 0x58; 0x41; 0x69; 0x81; 0x72; 0x19; 756 + 0x08; 0x83; 0x9b; 0x92; 0x10; 0x4e; 0x62; 0x2d; 0x7b; 0x46; 0x70; 0x43; 0x6e; 0xa3; 0x53; 0x13; 757 + 0x1f; 0xe2; 0x93; 0xa6; 0x23; 0x5b; 0xf7; 0x92; 0x3e; 0x37; 0x14; 0x75; 0x3b; 0xb9; 0x4b; 0x24; 758 + 0x41; 0x2e; 0xa5; 0x3d; 0x48; 0x0d; 0x0f; 0x99; 0xea; 0x1e; 0x42; 0x97; 0xc6; 0xfe; 0x95; 0xda; 759 + 0xab; 0x47; 0x9a; 0xcb; 0x2b; 0x03; 0xd6; 0x0d; 0x40; 0xc1; 0x0a; 0xf7; 0x78; 0x1a; 0xda; 0xb5; 760 + 0x83; 0xa4; 0xad; 0xb5; 0x99; 0x49; 0x20; 0x2e; 0xf8; 0x93; 0x3c; 0x1e; 0x6c; 0x3d; 0xd1; 0x3b; 761 + 0x23; 0x3a; 0x6b; 0x38; 0x2a; 0x7e; 0x62; 0x7a; 0x5f; 0xdd; 0x17; 0x05; 0x75; 0xd0; 0x24; 0x5d; 762 + 0xbe; 0x8d; 0xa8; 0x9a; 0x10; 0x44; 0xfa; 0xd2; 0xb4; 0xca; 0xef; 0xd7; 0xd0; 0xb5; 0x76; 0xa5; 763 + 0x26; 0x25; 0x1c; 0x08; 0x41; 0xd8; 0x64; 0x92; 0xa7; 0xaf; 0x7d; 0xfe; 0x88; 0x40; 0x39; 0x61; 764 + 0x0b; 0xc0; 0x48; 0x30; 0xa9; 0x82; 0x34; 0xad; 0xf7; 0x70; 0x46; 0x03; 0x7c; 0x35; 0x91; 0x3a; 765 + 0xd5; 0xbb; 0x24; 0xd8; 0x01; 0xbc; 0x14; 0xf0; 0xc3; 0x0f; 0x23; 0x3b; 0x58; 0x32; 0xba; 0x0f; 766 + 0x12; 0x6c; 0x66; 0x7a; 0x6d; 0x9d; 0xe4; 0xf0; 0xe5; 0x7c; 0x5d; 0x7e; 0x02; 0xd8; 0xd7; 0xac; 767 + 0x89; 0x97; 0x0b; 0x61; 0xb7; 0x36; 0x9f; 0xb0; 0x7d; 0x3b; 0xee; 0xb7; 0x33; 0x69; 768 + ] in 769 + let gh2 = list_to_cstruct [ 0x30; 0x82; 0x04; 0xb6; 0x30; 0x82; 0x03; 0x9e; 0xa0; 0x03; 0x02; 0x01; 0x02; 0x02; 0x10; 770 + 0x0c; 0x79; 0xa9; 0x44; 0xb0; 0x8c; 0x11; 0x95; 0x20; 0x92; 0x61; 0x5f; 0xe2; 0x6b; 0x1d; 0x83; 771 + 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 0xf7; 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x30; 772 + 0x6c; 0x31; 0x0b; 0x30; 0x09; 0x06; 0x03; 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x15; 773 + 0x30; 0x13; 0x06; 0x03; 0x55; 0x04; 0x0a; 0x13; 0x0c; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 774 + 0x74; 0x20; 0x49; 0x6e; 0x63; 0x31; 0x19; 0x30; 0x17; 0x06; 0x03; 0x55; 0x04; 0x0b; 0x13; 0x10; 775 + 0x77; 0x77; 0x77; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 776 + 0x31; 0x2b; 0x30; 0x29; 0x06; 0x03; 0x55; 0x04; 0x03; 0x13; 0x22; 0x44; 0x69; 0x67; 0x69; 0x43; 777 + 0x65; 0x72; 0x74; 0x20; 0x48; 0x69; 0x67; 0x68; 0x20; 0x41; 0x73; 0x73; 0x75; 0x72; 0x61; 0x6e; 778 + 0x63; 0x65; 0x20; 0x45; 0x56; 0x20; 0x52; 0x6f; 0x6f; 0x74; 0x20; 0x43; 0x41; 0x30; 0x1e; 0x17; 779 + 0x0d; 0x31; 0x33; 0x31; 0x30; 0x32; 0x32; 0x31; 0x32; 0x30; 0x30; 0x30; 0x30; 0x5a; 0x17; 0x0d; 780 + 0x32; 0x38; 0x31; 0x30; 0x32; 0x32; 0x31; 0x32; 0x30; 0x30; 0x30; 0x30; 0x5a; 0x30; 0x75; 0x31; 781 + 0x0b; 0x30; 0x09; 0x06; 0x03; 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x15; 0x30; 0x13; 782 + 0x06; 0x03; 0x55; 0x04; 0x0a; 0x13; 0x0c; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x20; 783 + 0x49; 0x6e; 0x63; 0x31; 0x19; 0x30; 0x17; 0x06; 0x03; 0x55; 0x04; 0x0b; 0x13; 0x10; 0x77; 0x77; 784 + 0x77; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x31; 0x34; 785 + 0x30; 0x32; 0x06; 0x03; 0x55; 0x04; 0x03; 0x13; 0x2b; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 786 + 0x74; 0x20; 0x53; 0x48; 0x41; 0x32; 0x20; 0x45; 0x78; 0x74; 0x65; 0x6e; 0x64; 0x65; 0x64; 0x20; 787 + 0x56; 0x61; 0x6c; 0x69; 0x64; 0x61; 0x74; 0x69; 0x6f; 0x6e; 0x20; 0x53; 0x65; 0x72; 0x76; 0x65; 788 + 0x72; 0x20; 0x43; 0x41; 0x30; 0x82; 0x01; 0x22; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 789 + 0xf7; 0x0d; 0x01; 0x01; 0x01; 0x05; 0x00; 0x03; 0x82; 0x01; 0x0f; 0x00; 0x30; 0x82; 0x01; 0x0a; 790 + 0x02; 0x82; 0x01; 0x01; 0x00; 0xd7; 0x53; 0xa4; 0x04; 0x51; 0xf8; 0x99; 0xa6; 0x16; 0x48; 0x4b; 791 + 0x67; 0x27; 0xaa; 0x93; 0x49; 0xd0; 0x39; 0xed; 0x0c; 0xb0; 0xb0; 0x00; 0x87; 0xf1; 0x67; 0x28; 792 + 0x86; 0x85; 0x8c; 0x8e; 0x63; 0xda; 0xbc; 0xb1; 0x40; 0x38; 0xe2; 0xd3; 0xf5; 0xec; 0xa5; 0x05; 793 + 0x18; 0xb8; 0x3d; 0x3e; 0xc5; 0x99; 0x17; 0x32; 0xec; 0x18; 0x8c; 0xfa; 0xf1; 0x0c; 0xa6; 0x64; 794 + 0x21; 0x85; 0xcb; 0x07; 0x10; 0x34; 0xb0; 0x52; 0x88; 0x2b; 0x1f; 0x68; 0x9b; 0xd2; 0xb1; 0x8f; 795 + 0x12; 0xb0; 0xb3; 0xd2; 0xe7; 0x88; 0x1f; 0x1f; 0xef; 0x38; 0x77; 0x54; 0x53; 0x5f; 0x80; 0x79; 796 + 0x3f; 0x2e; 0x1a; 0xaa; 0xa8; 0x1e; 0x4b; 0x2b; 0x0d; 0xab; 0xb7; 0x63; 0xb9; 0x35; 0xb7; 0x7d; 797 + 0x14; 0xbc; 0x59; 0x4b; 0xdf; 0x51; 0x4a; 0xd2; 0xa1; 0xe2; 0x0c; 0xe2; 0x90; 0x82; 0x87; 0x6a; 798 + 0xae; 0xea; 0xd7; 0x64; 0xd6; 0x98; 0x55; 0xe8; 0xfd; 0xaf; 0x1a; 0x50; 0x6c; 0x54; 0xbc; 0x11; 799 + 0xf2; 0xfd; 0x4a; 0xf2; 0x9d; 0xbb; 0x7f; 0x0e; 0xf4; 0xd5; 0xbe; 0x8e; 0x16; 0x89; 0x12; 0x55; 800 + 0xd8; 0xc0; 0x71; 0x34; 0xee; 0xf6; 0xdc; 0x2d; 0xec; 0xc4; 0x87; 0x25; 0x86; 0x8d; 0xd8; 0x21; 801 + 0xe4; 0xb0; 0x4d; 0x0c; 0x89; 0xdc; 0x39; 0x26; 0x17; 0xdd; 0xf6; 0xd7; 0x94; 0x85; 0xd8; 0x04; 802 + 0x21; 0x70; 0x9d; 0x6f; 0x6f; 0xff; 0x5c; 0xba; 0x19; 0xe1; 0x45; 0xcb; 0x56; 0x57; 0x28; 0x7e; 803 + 0x1c; 0x0d; 0x41; 0x57; 0xaa; 0xb7; 0xb8; 0x27; 0xbb; 0xb1; 0xe4; 0xfa; 0x2a; 0xef; 0x21; 0x23; 804 + 0x75; 0x1a; 0xad; 0x2d; 0x9b; 0x86; 0x35; 0x8c; 0x9c; 0x77; 0xb5; 0x73; 0xad; 0xd8; 0x94; 0x2d; 805 + 0xe4; 0xf3; 0x0c; 0x9d; 0xee; 0xc1; 0x4e; 0x62; 0x7e; 0x17; 0xc0; 0x71; 0x9e; 0x2c; 0xde; 0xf1; 806 + 0xf9; 0x10; 0x28; 0x19; 0x33; 0x02; 0x03; 0x01; 0x00; 0x01; 0xa3; 0x82; 0x01; 0x49; 0x30; 0x82; 807 + 0x01; 0x45; 0x30; 0x12; 0x06; 0x03; 0x55; 0x1d; 0x13; 0x01; 0x01; 0xff; 0x04; 0x08; 0x30; 0x06; 808 + 0x01; 0x01; 0xff; 0x02; 0x01; 0x00; 0x30; 0x0e; 0x06; 0x03; 0x55; 0x1d; 0x0f; 0x01; 0x01; 0xff; 809 + 0x04; 0x04; 0x03; 0x02; 0x01; 0x86; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x25; 0x04; 0x16; 0x30; 810 + 0x14; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x03; 0x01; 0x06; 0x08; 0x2b; 0x06; 0x01; 811 + 0x05; 0x05; 0x07; 0x03; 0x02; 0x30; 0x34; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x01; 812 + 0x01; 0x04; 0x28; 0x30; 0x26; 0x30; 0x24; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x30; 813 + 0x01; 0x86; 0x18; 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x6f; 0x63; 0x73; 0x70; 0x2e; 0x64; 814 + 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x30; 0x4b; 0x06; 0x03; 0x55; 815 + 0x1d; 0x1f; 0x04; 0x44; 0x30; 0x42; 0x30; 0x40; 0xa0; 0x3e; 0xa0; 0x3c; 0x86; 0x3a; 0x68; 0x74; 816 + 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x63; 0x72; 0x6c; 0x34; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 817 + 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x2f; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x48; 818 + 0x69; 0x67; 0x68; 0x41; 0x73; 0x73; 0x75; 0x72; 0x61; 0x6e; 0x63; 0x65; 0x45; 0x56; 0x52; 0x6f; 819 + 0x6f; 0x74; 0x43; 0x41; 0x2e; 0x63; 0x72; 0x6c; 0x30; 0x3d; 0x06; 0x03; 0x55; 0x1d; 0x20; 0x04; 820 + 0x36; 0x30; 0x34; 0x30; 0x32; 0x06; 0x04; 0x55; 0x1d; 0x20; 0x00; 0x30; 0x2a; 0x30; 0x28; 0x06; 821 + 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x02; 0x01; 0x16; 0x1c; 0x68; 0x74; 0x74; 0x70; 0x73; 822 + 0x3a; 0x2f; 0x2f; 0x77; 0x77; 0x77; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 823 + 0x63; 0x6f; 0x6d; 0x2f; 0x43; 0x50; 0x53; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x0e; 0x04; 0x16; 824 + 0x04; 0x14; 0x3d; 0xd3; 0x50; 0xa5; 0xd6; 0xa0; 0xad; 0xee; 0xf3; 0x4a; 0x60; 0x0a; 0x65; 0xd3; 825 + 0x21; 0xd4; 0xf8; 0xf8; 0xd6; 0x0f; 0x30; 0x1f; 0x06; 0x03; 0x55; 0x1d; 0x23; 0x04; 0x18; 0x30; 826 + 0x16; 0x80; 0x14; 0xb1; 0x3e; 0xc3; 0x69; 0x03; 0xf8; 0xbf; 0x47; 0x01; 0xd4; 0x98; 0x26; 0x1a; 827 + 0x08; 0x02; 0xef; 0x63; 0x64; 0x2b; 0xc3; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 0xf7; 828 + 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x03; 0x82; 0x01; 0x01; 0x00; 0x9d; 0xb6; 0xd0; 0x90; 0x86; 829 + 0xe1; 0x86; 0x02; 0xed; 0xc5; 0xa0; 0xf0; 0x34; 0x1c; 0x74; 0xc1; 0x8d; 0x76; 0xcc; 0x86; 0x0a; 830 + 0xa8; 0xf0; 0x4a; 0x8a; 0x42; 0xd6; 0x3f; 0xc8; 0xa9; 0x4d; 0xad; 0x7c; 0x08; 0xad; 0xe6; 0xb6; 831 + 0x50; 0xb8; 0xa2; 0x1a; 0x4d; 0x88; 0x07; 0xb1; 0x29; 0x21; 0xdc; 0xe7; 0xda; 0xc6; 0x3c; 0x21; 832 + 0xe0; 0xe3; 0x11; 0x49; 0x70; 0xac; 0x7a; 0x1d; 0x01; 0xa4; 0xca; 0x11; 0x3a; 0x57; 0xab; 0x7d; 833 + 0x57; 0x2a; 0x40; 0x74; 0xfd; 0xd3; 0x1d; 0x85; 0x18; 0x50; 0xdf; 0x57; 0x47; 0x75; 0xa1; 0x7d; 834 + 0x55; 0x20; 0x2e; 0x47; 0x37; 0x50; 0x72; 0x8c; 0x7f; 0x82; 0x1b; 0xd2; 0x62; 0x8f; 0x2d; 0x03; 835 + 0x5a; 0xda; 0xc3; 0xc8; 0xa1; 0xce; 0x2c; 0x52; 0xa2; 0x00; 0x63; 0xeb; 0x73; 0xba; 0x71; 0xc8; 836 + 0x49; 0x27; 0x23; 0x97; 0x64; 0x85; 0x9e; 0x38; 0x0e; 0xad; 0x63; 0x68; 0x3c; 0xba; 0x52; 0x81; 837 + 0x58; 0x79; 0xa3; 0x2c; 0x0c; 0xdf; 0xde; 0x6d; 0xeb; 0x31; 0xf2; 0xba; 0xa0; 0x7c; 0x6c; 0xf1; 838 + 0x2c; 0xd4; 0xe1; 0xbd; 0x77; 0x84; 0x37; 0x03; 0xce; 0x32; 0xb5; 0xc8; 0x9a; 0x81; 0x1a; 0x4a; 839 + 0x92; 0x4e; 0x3b; 0x46; 0x9a; 0x85; 0xfe; 0x83; 0xa2; 0xf9; 0x9e; 0x8c; 0xa3; 0xcc; 0x0d; 0x5e; 840 + 0xb3; 0x3d; 0xcf; 0x04; 0x78; 0x8f; 0x14; 0x14; 0x7b; 0x32; 0x9c; 0xc7; 0x00; 0xa6; 0x5c; 0xc4; 841 + 0xb5; 0xa1; 0x55; 0x8d; 0x5a; 0x56; 0x68; 0xa4; 0x22; 0x70; 0xaa; 0x3c; 0x81; 0x71; 0xd9; 0x9d; 842 + 0xa8; 0x45; 0x3b; 0xf4; 0xe5; 0xf6; 0xa2; 0x51; 0xdd; 0xc7; 0x7b; 0x62; 0xe8; 0x6f; 0x0c; 0x74; 843 + 0xeb; 0xb8; 0xda; 0xf8; 0xbf; 0x87; 0x0d; 0x79; 0x50; 0x91; 0x90; 0x9b; 0x18; 0x3b; 0x91; 0x59; 844 + 0x27; 0xf1; 0x35; 0x28; 0x13; 0xab; 0x26; 0x7e; 0xd5; 0xf7; 0x7a ] in 845 + 846 + 847 + [ ([12; 0; 0; 12] @ data , (Core.ServerKeyExchange data_cs)) ; 848 + ([20; 0; 0; 12] @ data , (Core.Finished data_cs)) ; 849 + ([16; 0; 0; 12] @ data , (Core.ClientKeyExchange data_cs)) ; 850 + 851 + ([11; 0; 0; 3; 0; 0; 0] , (Core.Certificate (Writer.assemble_certificates []))) ; 852 + ([11; 0; 0; 18; 0; 0; 15; 0; 0; 12] @ data , (Core.Certificate (Writer.assemble_certificates [data_cs]))) ; 853 + ([11; 0; 0; 33; 0; 0; 30; 0; 0; 12] @ data @ [0; 0; 12] @ data , 854 + (Core.Certificate (Writer.assemble_certificates [data_cs ; data_cs]))) ; 855 + 856 + ([ 857 + 0x0b; 0x00; 0x0a; 0xa7; 858 + 0x00; 0x0a; 0xa4; 859 + 0x00; 0x05; 0xe4; 860 + 0x30; 0x82; 0x05; 0xe0; 0x30; 0x82; 861 + 0x04; 0xc8; 0xa0; 0x03; 0x02; 0x01; 0x02; 0x02; 0x10; 0x0c; 0x00; 0x93; 0x10; 0xd2; 0x06; 0xdb; 862 + 0xe3; 0x37; 0x55; 0x35; 0x80; 0x11; 0x8d; 0xdc; 0x87; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 863 + 0x86; 0xf7; 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x30; 0x75; 0x31; 0x0b; 0x30; 0x09; 0x06; 0x03; 864 + 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x15; 0x30; 0x13; 0x06; 0x03; 0x55; 0x04; 0x0a; 865 + 0x13; 0x0c; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x20; 0x49; 0x6e; 0x63; 0x31; 0x19; 866 + 0x30; 0x17; 0x06; 0x03; 0x55; 0x04; 0x0b; 0x13; 0x10; 0x77; 0x77; 0x77; 0x2e; 0x64; 0x69; 0x67; 867 + 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x31; 0x34; 0x30; 0x32; 0x06; 0x03; 0x55; 868 + 0x04; 0x03; 0x13; 0x2b; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x20; 0x53; 0x48; 0x41; 869 + 0x32; 0x20; 0x45; 0x78; 0x74; 0x65; 0x6e; 0x64; 0x65; 0x64; 0x20; 0x56; 0x61; 0x6c; 0x69; 0x64; 870 + 0x61; 0x74; 0x69; 0x6f; 0x6e; 0x20; 0x53; 0x65; 0x72; 0x76; 0x65; 0x72; 0x20; 0x43; 0x41; 0x30; 871 + 0x1e; 0x17; 0x0d; 0x31; 0x34; 0x30; 0x34; 0x30; 0x38; 0x30; 0x30; 0x30; 0x30; 0x30; 0x30; 0x5a; 872 + 0x17; 0x0d; 0x31; 0x36; 0x30; 0x34; 0x31; 0x32; 0x31; 0x32; 0x30; 0x30; 0x30; 0x30; 0x5a; 0x30; 873 + 0x81; 0xf0; 0x31; 0x1d; 0x30; 0x1b; 0x06; 0x03; 0x55; 0x04; 0x0f; 0x0c; 0x14; 0x50; 0x72; 0x69; 874 + 0x76; 0x61; 0x74; 0x65; 0x20; 0x4f; 0x72; 0x67; 0x61; 0x6e; 0x69; 0x7a; 0x61; 0x74; 0x69; 0x6f; 875 + 0x6e; 0x31; 0x13; 0x30; 0x11; 0x06; 0x0b; 0x2b; 0x06; 0x01; 0x04; 0x01; 0x82; 0x37; 0x3c; 0x02; 876 + 0x01; 0x03; 0x13; 0x02; 0x55; 0x53; 0x31; 0x19; 0x30; 0x17; 0x06; 0x0b; 0x2b; 0x06; 0x01; 0x04; 877 + 0x01; 0x82; 0x37; 0x3c; 0x02; 0x01; 0x02; 0x13; 0x08; 0x44; 0x65; 0x6c; 0x61; 0x77; 0x61; 0x72; 878 + 0x65; 0x31; 0x10; 0x30; 0x0e; 0x06; 0x03; 0x55; 0x04; 0x05; 0x13; 0x07; 0x35; 0x31; 0x35; 0x37; 879 + 0x35; 0x35; 0x30; 0x31; 0x17; 0x30; 0x15; 0x06; 0x03; 0x55; 0x04; 0x09; 0x13; 0x0e; 0x35; 0x34; 880 + 0x38; 0x20; 0x34; 0x74; 0x68; 0x20; 0x53; 0x74; 0x72; 0x65; 0x65; 0x74; 0x31; 0x0e; 0x30; 0x0c; 881 + 0x06; 0x03; 0x55; 0x04; 0x11; 0x13; 0x05; 0x39; 0x34; 0x31; 0x30; 0x37; 0x31; 0x0b; 0x30; 0x09; 882 + 0x06; 0x03; 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x13; 0x30; 0x11; 0x06; 0x03; 0x55; 883 + 0x04; 0x08; 0x13; 0x0a; 0x43; 0x61; 0x6c; 0x69; 0x66; 0x6f; 0x72; 0x6e; 0x69; 0x61; 0x31; 0x16; 884 + 0x30; 0x14; 0x06; 0x03; 0x55; 0x04; 0x07; 0x13; 0x0d; 0x53; 0x61; 0x6e; 0x20; 0x46; 0x72; 0x61; 885 + 0x6e; 0x63; 0x69; 0x73; 0x63; 0x6f; 0x31; 0x15; 0x30; 0x13; 0x06; 0x03; 0x55; 0x04; 0x0a; 0x13; 886 + 0x0c; 0x47; 0x69; 0x74; 0x48; 0x75; 0x62; 0x2c; 0x20; 0x49; 0x6e; 0x63; 0x2e; 0x31; 0x13; 0x30; 887 + 0x11; 0x06; 0x03; 0x55; 0x04; 0x03; 0x13; 0x0a; 0x67; 0x69; 0x74; 0x68; 0x75; 0x62; 0x2e; 0x63; 888 + 0x6f; 0x6d; 0x30; 0x82; 0x01; 0x22; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 0xf7; 0x0d; 889 + 0x01; 0x01; 0x01; 0x05; 0x00; 0x03; 0x82; 0x01; 0x0f; 0x00; 0x30; 0x82; 0x01; 0x0a; 0x02; 0x82; 890 + 0x01; 0x01; 0x00; 0xb1; 0xd4; 0xdc; 0x3c; 0xaf; 0xfd; 0xf3; 0x4e; 0xed; 0xc1; 0x67; 0xad; 0xe6; 891 + 0xcb; 0x22; 0xe8; 0xb7; 0xe2; 0xab; 0x28; 0xf2; 0xf7; 0xdc; 0x62; 0x70; 0x08; 0xd1; 0x0c; 0xaf; 892 + 0xd6; 0x16; 0x6a; 0x21; 0xb0; 0x36; 0x4b; 0x17; 0x0d; 0x36; 0x63; 0x04; 0xae; 0xbf; 0xea; 0x20; 893 + 0x51; 0x95; 0x65; 0x66; 0xf2; 0xbf; 0xb9; 0x4d; 0xa4; 0x0c; 0x29; 0xeb; 0xf5; 0x15; 0xb1; 0xe8; 894 + 0x35; 0xb3; 0x70; 0x10; 0x94; 0xd5; 0x1b; 0x59; 0xb4; 0x26; 0x0f; 0xd6; 0x83; 0x57; 0x59; 0x9d; 895 + 0xe1; 0x7c; 0x09; 0xdd; 0xe0; 0x13; 0xca; 0x4d; 0x6f; 0x43; 0x9b; 0xcd; 0xcf; 0x87; 0x3a; 0x15; 896 + 0xa7; 0x85; 0xdd; 0x66; 0x83; 0xed; 0x93; 0x0c; 0xfe; 0x2b; 0x6d; 0x38; 0x1c; 0x79; 0x88; 0x90; 897 + 0xcf; 0xad; 0x58; 0x18; 0x2d; 0x51; 0xd1; 0xc2; 0xa3; 0xf2; 0x47; 0x8c; 0x6f; 0x38; 0x09; 0xb9; 898 + 0xb8; 0xef; 0x4c; 0x93; 0x0b; 0xcb; 0x83; 0x94; 0x87; 0xea; 0xe0; 0xa3; 0xb5; 0xd9; 0x7b; 0x9b; 899 + 0x6b; 0x0f; 0x43; 0xf9; 0xca; 0xee; 0x80; 0x0d; 0x28; 0xa7; 0x76; 0xf1; 0x25; 0xf4; 0xc1; 0x35; 900 + 0x3c; 0xf6; 0x74; 0xad; 0xde; 0x6a; 0x33; 0x82; 0x7b; 0xdc; 0xfd; 0x4b; 0x76; 0xa7; 0xc2; 0xee; 901 + 0xf2; 0x6a; 0xbf; 0xa9; 0x24; 0xa6; 0x5f; 0xe7; 0x2e; 0x7c; 0x0e; 0xdb; 0xc3; 0x74; 0x73; 0xfa; 902 + 0x7e; 0xc6; 0xd8; 0xcf; 0x60; 0xeb; 0x36; 0x56; 0x21; 0xb6; 0xc1; 0x8a; 0xb8; 0x24; 0x82; 0x4d; 903 + 0x78; 0x24; 0xba; 0xe9; 0x1d; 0xa1; 0x8a; 0xa7; 0x87; 0xbe; 0x66; 0x25; 0x69; 0xbf; 0xbe; 0x3b; 904 + 0x72; 0x6e; 0x4f; 0xe0; 0xe4; 0x85; 0x25; 0x08; 0xb1; 0x91; 0x89; 0xb8; 0xd6; 0x74; 0x65; 0x76; 905 + 0x9b; 0x2c; 0x4f; 0x62; 0x1f; 0xa1; 0xfa; 0x3a; 0xbe; 0x9c; 0x24; 0xbf; 0x9f; 0xca; 0xb0; 0xc5; 906 + 0xc0; 0x67; 0x8d; 0x02; 0x03; 0x01; 0x00; 0x01; 0xa3; 0x82; 0x01; 0xee; 0x30; 0x82; 0x01; 0xea; 907 + 0x30; 0x1f; 0x06; 0x03; 0x55; 0x1d; 0x23; 0x04; 0x18; 0x30; 0x16; 0x80; 0x14; 0x3d; 0xd3; 0x50; 908 + 0xa5; 0xd6; 0xa0; 0xad; 0xee; 0xf3; 0x4a; 0x60; 0x0a; 0x65; 0xd3; 0x21; 0xd4; 0xf8; 0xf8; 0xd6; 909 + 0x0f; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x0e; 0x04; 0x16; 0x04; 0x14; 0x6a; 0x43; 0x90; 0x7d; 910 + 0x3b; 0x98; 0x14; 0x72; 0x52; 0x95; 0x3a; 0xaa; 0x28; 0x0a; 0x43; 0xf8; 0x51; 0x7e; 0xd3; 0xa6; 911 + 0x30; 0x25; 0x06; 0x03; 0x55; 0x1d; 0x11; 0x04; 0x1e; 0x30; 0x1c; 0x82; 0x0a; 0x67; 0x69; 0x74; 912 + 0x68; 0x75; 0x62; 0x2e; 0x63; 0x6f; 0x6d; 0x82; 0x0e; 0x77; 0x77; 0x77; 0x2e; 0x67; 0x69; 0x74; 913 + 0x68; 0x75; 0x62; 0x2e; 0x63; 0x6f; 0x6d; 0x30; 0x0e; 0x06; 0x03; 0x55; 0x1d; 0x0f; 0x01; 0x01; 914 + 0xff; 0x04; 0x04; 0x03; 0x02; 0x05; 0xa0; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x25; 0x04; 0x16; 915 + 0x30; 0x14; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x03; 0x01; 0x06; 0x08; 0x2b; 0x06; 916 + 0x01; 0x05; 0x05; 0x07; 0x03; 0x02; 0x30; 0x75; 0x06; 0x03; 0x55; 0x1d; 0x1f; 0x04; 0x6e; 0x30; 917 + 0x6c; 0x30; 0x34; 0xa0; 0x32; 0xa0; 0x30; 0x86; 0x2e; 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 918 + 0x63; 0x72; 0x6c; 0x33; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 919 + 0x6d; 0x2f; 0x73; 0x68; 0x61; 0x32; 0x2d; 0x65; 0x76; 0x2d; 0x73; 0x65; 0x72; 0x76; 0x65; 0x72; 920 + 0x2d; 0x67; 0x31; 0x2e; 0x63; 0x72; 0x6c; 0x30; 0x34; 0xa0; 0x32; 0xa0; 0x30; 0x86; 0x2e; 0x68; 921 + 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x63; 0x72; 0x6c; 0x34; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 922 + 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x2f; 0x73; 0x68; 0x61; 0x32; 0x2d; 0x65; 0x76; 0x2d; 923 + 0x73; 0x65; 0x72; 0x76; 0x65; 0x72; 0x2d; 0x67; 0x31; 0x2e; 0x63; 0x72; 0x6c; 0x30; 0x42; 0x06; 924 + 0x03; 0x55; 0x1d; 0x20; 0x04; 0x3b; 0x30; 0x39; 0x30; 0x37; 0x06; 0x09; 0x60; 0x86; 0x48; 0x01; 925 + 0x86; 0xfd; 0x6c; 0x02; 0x01; 0x30; 0x2a; 0x30; 0x28; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 926 + 0x07; 0x02; 0x01; 0x16; 0x1c; 0x68; 0x74; 0x74; 0x70; 0x73; 0x3a; 0x2f; 0x2f; 0x77; 0x77; 0x77; 927 + 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x2f; 0x43; 0x50; 928 + 0x53; 0x30; 0x81; 0x88; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x01; 0x01; 0x04; 0x7c; 929 + 0x30; 0x7a; 0x30; 0x24; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x30; 0x01; 0x86; 0x18; 930 + 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x6f; 0x63; 0x73; 0x70; 0x2e; 0x64; 0x69; 0x67; 0x69; 931 + 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x30; 0x52; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 932 + 0x05; 0x07; 0x30; 0x02; 0x86; 0x46; 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x63; 0x61; 0x63; 933 + 0x65; 0x72; 0x74; 0x73; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 934 + 0x6d; 0x2f; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x53; 0x48; 0x41; 0x32; 0x45; 0x78; 935 + 0x74; 0x65; 0x6e; 0x64; 0x65; 0x64; 0x56; 0x61; 0x6c; 0x69; 0x64; 0x61; 0x74; 0x69; 0x6f; 0x6e; 936 + 0x53; 0x65; 0x72; 0x76; 0x65; 0x72; 0x43; 0x41; 0x2e; 0x63; 0x72; 0x74; 0x30; 0x0c; 0x06; 0x03; 937 + 0x55; 0x1d; 0x13; 0x01; 0x01; 0xff; 0x04; 0x02; 0x30; 0x00; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 938 + 0x48; 0x86; 0xf7; 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x03; 0x82; 0x01; 0x01; 0x00; 0x6f; 0xe7; 939 + 0x6d; 0xcb; 0x82; 0xf3; 0xef; 0x90; 0x87; 0x09; 0xd7; 0x0f; 0x15; 0x22; 0x2c; 0x8c; 0xfe; 0xd3; 940 + 0xab; 0x1c; 0x8a; 0x96; 0xdb; 0x5d; 0x12; 0x5d; 0xd1; 0x78; 0xc0; 0x31; 0xb0; 0xff; 0x45; 0xc8; 941 + 0x89; 0xf7; 0x08; 0x98; 0x52; 0x17; 0x1f; 0x4c; 0x4b; 0x20; 0x64; 0x6a; 0x6d; 0xdb; 0x50; 0xd7; 942 + 0x10; 0xbe; 0x7e; 0xab; 0xfe; 0x2f; 0x80; 0xd8; 0xa9; 0x4a; 0x58; 0x41; 0x69; 0x81; 0x72; 0x19; 943 + 0x08; 0x83; 0x9b; 0x92; 0x10; 0x4e; 0x62; 0x2d; 0x7b; 0x46; 0x70; 0x43; 0x6e; 0xa3; 0x53; 0x13; 944 + 0x1f; 0xe2; 0x93; 0xa6; 0x23; 0x5b; 0xf7; 0x92; 0x3e; 0x37; 0x14; 0x75; 0x3b; 0xb9; 0x4b; 0x24; 945 + 0x41; 0x2e; 0xa5; 0x3d; 0x48; 0x0d; 0x0f; 0x99; 0xea; 0x1e; 0x42; 0x97; 0xc6; 0xfe; 0x95; 0xda; 946 + 0xab; 0x47; 0x9a; 0xcb; 0x2b; 0x03; 0xd6; 0x0d; 0x40; 0xc1; 0x0a; 0xf7; 0x78; 0x1a; 0xda; 0xb5; 947 + 0x83; 0xa4; 0xad; 0xb5; 0x99; 0x49; 0x20; 0x2e; 0xf8; 0x93; 0x3c; 0x1e; 0x6c; 0x3d; 0xd1; 0x3b; 948 + 0x23; 0x3a; 0x6b; 0x38; 0x2a; 0x7e; 0x62; 0x7a; 0x5f; 0xdd; 0x17; 0x05; 0x75; 0xd0; 0x24; 0x5d; 949 + 0xbe; 0x8d; 0xa8; 0x9a; 0x10; 0x44; 0xfa; 0xd2; 0xb4; 0xca; 0xef; 0xd7; 0xd0; 0xb5; 0x76; 0xa5; 950 + 0x26; 0x25; 0x1c; 0x08; 0x41; 0xd8; 0x64; 0x92; 0xa7; 0xaf; 0x7d; 0xfe; 0x88; 0x40; 0x39; 0x61; 951 + 0x0b; 0xc0; 0x48; 0x30; 0xa9; 0x82; 0x34; 0xad; 0xf7; 0x70; 0x46; 0x03; 0x7c; 0x35; 0x91; 0x3a; 952 + 0xd5; 0xbb; 0x24; 0xd8; 0x01; 0xbc; 0x14; 0xf0; 0xc3; 0x0f; 0x23; 0x3b; 0x58; 0x32; 0xba; 0x0f; 953 + 0x12; 0x6c; 0x66; 0x7a; 0x6d; 0x9d; 0xe4; 0xf0; 0xe5; 0x7c; 0x5d; 0x7e; 0x02; 0xd8; 0xd7; 0xac; 954 + 0x89; 0x97; 0x0b; 0x61; 0xb7; 0x36; 0x9f; 0xb0; 0x7d; 0x3b; 0xee; 0xb7; 0x33; 0x69; 955 + 0x00; 0x04; 0xba; 956 + 0x30; 0x82; 0x04; 0xb6; 0x30; 0x82; 0x03; 0x9e; 0xa0; 0x03; 0x02; 0x01; 0x02; 0x02; 0x10; 957 + 0x0c; 0x79; 0xa9; 0x44; 0xb0; 0x8c; 0x11; 0x95; 0x20; 0x92; 0x61; 0x5f; 0xe2; 0x6b; 0x1d; 0x83; 958 + 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 0xf7; 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x30; 959 + 0x6c; 0x31; 0x0b; 0x30; 0x09; 0x06; 0x03; 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x15; 960 + 0x30; 0x13; 0x06; 0x03; 0x55; 0x04; 0x0a; 0x13; 0x0c; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 961 + 0x74; 0x20; 0x49; 0x6e; 0x63; 0x31; 0x19; 0x30; 0x17; 0x06; 0x03; 0x55; 0x04; 0x0b; 0x13; 0x10; 962 + 0x77; 0x77; 0x77; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 963 + 0x31; 0x2b; 0x30; 0x29; 0x06; 0x03; 0x55; 0x04; 0x03; 0x13; 0x22; 0x44; 0x69; 0x67; 0x69; 0x43; 964 + 0x65; 0x72; 0x74; 0x20; 0x48; 0x69; 0x67; 0x68; 0x20; 0x41; 0x73; 0x73; 0x75; 0x72; 0x61; 0x6e; 965 + 0x63; 0x65; 0x20; 0x45; 0x56; 0x20; 0x52; 0x6f; 0x6f; 0x74; 0x20; 0x43; 0x41; 0x30; 0x1e; 0x17; 966 + 0x0d; 0x31; 0x33; 0x31; 0x30; 0x32; 0x32; 0x31; 0x32; 0x30; 0x30; 0x30; 0x30; 0x5a; 0x17; 0x0d; 967 + 0x32; 0x38; 0x31; 0x30; 0x32; 0x32; 0x31; 0x32; 0x30; 0x30; 0x30; 0x30; 0x5a; 0x30; 0x75; 0x31; 968 + 0x0b; 0x30; 0x09; 0x06; 0x03; 0x55; 0x04; 0x06; 0x13; 0x02; 0x55; 0x53; 0x31; 0x15; 0x30; 0x13; 969 + 0x06; 0x03; 0x55; 0x04; 0x0a; 0x13; 0x0c; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x20; 970 + 0x49; 0x6e; 0x63; 0x31; 0x19; 0x30; 0x17; 0x06; 0x03; 0x55; 0x04; 0x0b; 0x13; 0x10; 0x77; 0x77; 971 + 0x77; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x31; 0x34; 972 + 0x30; 0x32; 0x06; 0x03; 0x55; 0x04; 0x03; 0x13; 0x2b; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 973 + 0x74; 0x20; 0x53; 0x48; 0x41; 0x32; 0x20; 0x45; 0x78; 0x74; 0x65; 0x6e; 0x64; 0x65; 0x64; 0x20; 974 + 0x56; 0x61; 0x6c; 0x69; 0x64; 0x61; 0x74; 0x69; 0x6f; 0x6e; 0x20; 0x53; 0x65; 0x72; 0x76; 0x65; 975 + 0x72; 0x20; 0x43; 0x41; 0x30; 0x82; 0x01; 0x22; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 976 + 0xf7; 0x0d; 0x01; 0x01; 0x01; 0x05; 0x00; 0x03; 0x82; 0x01; 0x0f; 0x00; 0x30; 0x82; 0x01; 0x0a; 977 + 0x02; 0x82; 0x01; 0x01; 0x00; 0xd7; 0x53; 0xa4; 0x04; 0x51; 0xf8; 0x99; 0xa6; 0x16; 0x48; 0x4b; 978 + 0x67; 0x27; 0xaa; 0x93; 0x49; 0xd0; 0x39; 0xed; 0x0c; 0xb0; 0xb0; 0x00; 0x87; 0xf1; 0x67; 0x28; 979 + 0x86; 0x85; 0x8c; 0x8e; 0x63; 0xda; 0xbc; 0xb1; 0x40; 0x38; 0xe2; 0xd3; 0xf5; 0xec; 0xa5; 0x05; 980 + 0x18; 0xb8; 0x3d; 0x3e; 0xc5; 0x99; 0x17; 0x32; 0xec; 0x18; 0x8c; 0xfa; 0xf1; 0x0c; 0xa6; 0x64; 981 + 0x21; 0x85; 0xcb; 0x07; 0x10; 0x34; 0xb0; 0x52; 0x88; 0x2b; 0x1f; 0x68; 0x9b; 0xd2; 0xb1; 0x8f; 982 + 0x12; 0xb0; 0xb3; 0xd2; 0xe7; 0x88; 0x1f; 0x1f; 0xef; 0x38; 0x77; 0x54; 0x53; 0x5f; 0x80; 0x79; 983 + 0x3f; 0x2e; 0x1a; 0xaa; 0xa8; 0x1e; 0x4b; 0x2b; 0x0d; 0xab; 0xb7; 0x63; 0xb9; 0x35; 0xb7; 0x7d; 984 + 0x14; 0xbc; 0x59; 0x4b; 0xdf; 0x51; 0x4a; 0xd2; 0xa1; 0xe2; 0x0c; 0xe2; 0x90; 0x82; 0x87; 0x6a; 985 + 0xae; 0xea; 0xd7; 0x64; 0xd6; 0x98; 0x55; 0xe8; 0xfd; 0xaf; 0x1a; 0x50; 0x6c; 0x54; 0xbc; 0x11; 986 + 0xf2; 0xfd; 0x4a; 0xf2; 0x9d; 0xbb; 0x7f; 0x0e; 0xf4; 0xd5; 0xbe; 0x8e; 0x16; 0x89; 0x12; 0x55; 987 + 0xd8; 0xc0; 0x71; 0x34; 0xee; 0xf6; 0xdc; 0x2d; 0xec; 0xc4; 0x87; 0x25; 0x86; 0x8d; 0xd8; 0x21; 988 + 0xe4; 0xb0; 0x4d; 0x0c; 0x89; 0xdc; 0x39; 0x26; 0x17; 0xdd; 0xf6; 0xd7; 0x94; 0x85; 0xd8; 0x04; 989 + 0x21; 0x70; 0x9d; 0x6f; 0x6f; 0xff; 0x5c; 0xba; 0x19; 0xe1; 0x45; 0xcb; 0x56; 0x57; 0x28; 0x7e; 990 + 0x1c; 0x0d; 0x41; 0x57; 0xaa; 0xb7; 0xb8; 0x27; 0xbb; 0xb1; 0xe4; 0xfa; 0x2a; 0xef; 0x21; 0x23; 991 + 0x75; 0x1a; 0xad; 0x2d; 0x9b; 0x86; 0x35; 0x8c; 0x9c; 0x77; 0xb5; 0x73; 0xad; 0xd8; 0x94; 0x2d; 992 + 0xe4; 0xf3; 0x0c; 0x9d; 0xee; 0xc1; 0x4e; 0x62; 0x7e; 0x17; 0xc0; 0x71; 0x9e; 0x2c; 0xde; 0xf1; 993 + 0xf9; 0x10; 0x28; 0x19; 0x33; 0x02; 0x03; 0x01; 0x00; 0x01; 0xa3; 0x82; 0x01; 0x49; 0x30; 0x82; 994 + 0x01; 0x45; 0x30; 0x12; 0x06; 0x03; 0x55; 0x1d; 0x13; 0x01; 0x01; 0xff; 0x04; 0x08; 0x30; 0x06; 995 + 0x01; 0x01; 0xff; 0x02; 0x01; 0x00; 0x30; 0x0e; 0x06; 0x03; 0x55; 0x1d; 0x0f; 0x01; 0x01; 0xff; 996 + 0x04; 0x04; 0x03; 0x02; 0x01; 0x86; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x25; 0x04; 0x16; 0x30; 997 + 0x14; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x03; 0x01; 0x06; 0x08; 0x2b; 0x06; 0x01; 998 + 0x05; 0x05; 0x07; 0x03; 0x02; 0x30; 0x34; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x01; 999 + 0x01; 0x04; 0x28; 0x30; 0x26; 0x30; 0x24; 0x06; 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x30; 1000 + 0x01; 0x86; 0x18; 0x68; 0x74; 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x6f; 0x63; 0x73; 0x70; 0x2e; 0x64; 1001 + 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x30; 0x4b; 0x06; 0x03; 0x55; 1002 + 0x1d; 0x1f; 0x04; 0x44; 0x30; 0x42; 0x30; 0x40; 0xa0; 0x3e; 0xa0; 0x3c; 0x86; 0x3a; 0x68; 0x74; 1003 + 0x74; 0x70; 0x3a; 0x2f; 0x2f; 0x63; 0x72; 0x6c; 0x34; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 1004 + 0x72; 0x74; 0x2e; 0x63; 0x6f; 0x6d; 0x2f; 0x44; 0x69; 0x67; 0x69; 0x43; 0x65; 0x72; 0x74; 0x48; 1005 + 0x69; 0x67; 0x68; 0x41; 0x73; 0x73; 0x75; 0x72; 0x61; 0x6e; 0x63; 0x65; 0x45; 0x56; 0x52; 0x6f; 1006 + 0x6f; 0x74; 0x43; 0x41; 0x2e; 0x63; 0x72; 0x6c; 0x30; 0x3d; 0x06; 0x03; 0x55; 0x1d; 0x20; 0x04; 1007 + 0x36; 0x30; 0x34; 0x30; 0x32; 0x06; 0x04; 0x55; 0x1d; 0x20; 0x00; 0x30; 0x2a; 0x30; 0x28; 0x06; 1008 + 0x08; 0x2b; 0x06; 0x01; 0x05; 0x05; 0x07; 0x02; 0x01; 0x16; 0x1c; 0x68; 0x74; 0x74; 0x70; 0x73; 1009 + 0x3a; 0x2f; 0x2f; 0x77; 0x77; 0x77; 0x2e; 0x64; 0x69; 0x67; 0x69; 0x63; 0x65; 0x72; 0x74; 0x2e; 1010 + 0x63; 0x6f; 0x6d; 0x2f; 0x43; 0x50; 0x53; 0x30; 0x1d; 0x06; 0x03; 0x55; 0x1d; 0x0e; 0x04; 0x16; 1011 + 0x04; 0x14; 0x3d; 0xd3; 0x50; 0xa5; 0xd6; 0xa0; 0xad; 0xee; 0xf3; 0x4a; 0x60; 0x0a; 0x65; 0xd3; 1012 + 0x21; 0xd4; 0xf8; 0xf8; 0xd6; 0x0f; 0x30; 0x1f; 0x06; 0x03; 0x55; 0x1d; 0x23; 0x04; 0x18; 0x30; 1013 + 0x16; 0x80; 0x14; 0xb1; 0x3e; 0xc3; 0x69; 0x03; 0xf8; 0xbf; 0x47; 0x01; 0xd4; 0x98; 0x26; 0x1a; 1014 + 0x08; 0x02; 0xef; 0x63; 0x64; 0x2b; 0xc3; 0x30; 0x0d; 0x06; 0x09; 0x2a; 0x86; 0x48; 0x86; 0xf7; 1015 + 0x0d; 0x01; 0x01; 0x0b; 0x05; 0x00; 0x03; 0x82; 0x01; 0x01; 0x00; 0x9d; 0xb6; 0xd0; 0x90; 0x86; 1016 + 0xe1; 0x86; 0x02; 0xed; 0xc5; 0xa0; 0xf0; 0x34; 0x1c; 0x74; 0xc1; 0x8d; 0x76; 0xcc; 0x86; 0x0a; 1017 + 0xa8; 0xf0; 0x4a; 0x8a; 0x42; 0xd6; 0x3f; 0xc8; 0xa9; 0x4d; 0xad; 0x7c; 0x08; 0xad; 0xe6; 0xb6; 1018 + 0x50; 0xb8; 0xa2; 0x1a; 0x4d; 0x88; 0x07; 0xb1; 0x29; 0x21; 0xdc; 0xe7; 0xda; 0xc6; 0x3c; 0x21; 1019 + 0xe0; 0xe3; 0x11; 0x49; 0x70; 0xac; 0x7a; 0x1d; 0x01; 0xa4; 0xca; 0x11; 0x3a; 0x57; 0xab; 0x7d; 1020 + 0x57; 0x2a; 0x40; 0x74; 0xfd; 0xd3; 0x1d; 0x85; 0x18; 0x50; 0xdf; 0x57; 0x47; 0x75; 0xa1; 0x7d; 1021 + 0x55; 0x20; 0x2e; 0x47; 0x37; 0x50; 0x72; 0x8c; 0x7f; 0x82; 0x1b; 0xd2; 0x62; 0x8f; 0x2d; 0x03; 1022 + 0x5a; 0xda; 0xc3; 0xc8; 0xa1; 0xce; 0x2c; 0x52; 0xa2; 0x00; 0x63; 0xeb; 0x73; 0xba; 0x71; 0xc8; 1023 + 0x49; 0x27; 0x23; 0x97; 0x64; 0x85; 0x9e; 0x38; 0x0e; 0xad; 0x63; 0x68; 0x3c; 0xba; 0x52; 0x81; 1024 + 0x58; 0x79; 0xa3; 0x2c; 0x0c; 0xdf; 0xde; 0x6d; 0xeb; 0x31; 0xf2; 0xba; 0xa0; 0x7c; 0x6c; 0xf1; 1025 + 0x2c; 0xd4; 0xe1; 0xbd; 0x77; 0x84; 0x37; 0x03; 0xce; 0x32; 0xb5; 0xc8; 0x9a; 0x81; 0x1a; 0x4a; 1026 + 0x92; 0x4e; 0x3b; 0x46; 0x9a; 0x85; 0xfe; 0x83; 0xa2; 0xf9; 0x9e; 0x8c; 0xa3; 0xcc; 0x0d; 0x5e; 1027 + 0xb3; 0x3d; 0xcf; 0x04; 0x78; 0x8f; 0x14; 0x14; 0x7b; 0x32; 0x9c; 0xc7; 0x00; 0xa6; 0x5c; 0xc4; 1028 + 0xb5; 0xa1; 0x55; 0x8d; 0x5a; 0x56; 0x68; 0xa4; 0x22; 0x70; 0xaa; 0x3c; 0x81; 0x71; 0xd9; 0x9d; 1029 + 0xa8; 0x45; 0x3b; 0xf4; 0xe5; 0xf6; 0xa2; 0x51; 0xdd; 0xc7; 0x7b; 0x62; 0xe8; 0x6f; 0x0c; 0x74; 1030 + 0xeb; 0xb8; 0xda; 0xf8; 0xbf; 0x87; 0x0d; 0x79; 0x50; 0x91; 0x90; 0x9b; 0x18; 0x3b; 0x91; 0x59; 1031 + 0x27; 0xf1; 0x35; 0x28; 0x13; 0xab; 0x26; 0x7e; 0xd5; 0xf7; 0x7a ], 1032 + Core.Certificate (Writer.assemble_certificates [gh1 ; gh2]) ) 1033 + 1034 + 1035 + ] 1036 + 1037 + let cmp_handshake_cstruct hs hs' = 1038 + Core.(match hs, hs' with 1039 + | Finished xs, Finished ys -> assert_cs_eq xs ys 1040 + | ServerKeyExchange xs, ServerKeyExchange ys -> assert_cs_eq xs ys 1041 + | Certificate xs, Certificate ys -> assert_cs_eq xs ys 1042 + | ClientKeyExchange xs, ClientKeyExchange ys -> assert_cs_eq xs ys 1043 + | _ -> assert_failure "handshake cstruct data parser broken") 1044 + 1045 + let good_handshake_cstruct_data_parser (xs, res) _ = 1046 + let buf = list_to_cstruct xs in 1047 + match Reader.parse_handshake buf with 1048 + | Ok r -> cmp_handshake_cstruct r res 1049 + | Error _ -> assert_failure "handshake cstruct data parser failed" 1050 + 1051 + let good_handshake_cstruct_data_tests = 1052 + List.mapi 1053 + (fun i f -> "Parse good handshake " ^ string_of_int i >:: good_handshake_cstruct_data_parser f) 1054 + good_handshake_cstruct_data 1055 + 1056 + let bad_handshake_cstruct_data = 1057 + let data = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11 ] in 1058 + [ [12; 0; 0; 13] @ data ; 1059 + [12; 0; 0; 11] @ data ; 1060 + [20; 0; 1; 12] @ data ; 1061 + [20; 0; 0; 11] @ data ; 1062 + [16; 0; 0; 15; 0; 12] @ data ; 1063 + 1064 + [25; 0; 0; 14; 0; 12] @ data ; 1065 + [255; 0; 0; 14; 0; 12] @ data ; 1066 + 1067 + [11; 0; 0; 17; 0; 0; 15; 0; 0; 12] @ data ; 1068 + ] 1069 + 1070 + let bad_handshake_cstruct_data_parser xs _ = 1071 + let buf = list_to_cstruct xs in 1072 + match Reader.parse_handshake buf with 1073 + | Ok _ -> assert_failure "bad handshake cstruct parser won" 1074 + | Error _ -> () 1075 + 1076 + let bad_handshake_cstruct_data_tests = 1077 + List.mapi 1078 + (fun i f -> "Parse bad handshake " ^ string_of_int i >:: bad_handshake_cstruct_data_parser f) 1079 + bad_handshake_cstruct_data 1080 + 1081 + let bad_certificate_cstruct_data = 1082 + let data = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11 ] in 1083 + [ [11; 0; 0; 3; 0; 0; 2] ; 1084 + [11; 0; 0; 4; 0; 0; 0; 0] ; 1085 + [11; 0; 0; 18; 0; 0; 15; 0; 0; 11] @ data ; 1086 + [11; 0; 0; 18; 0; 0; 14; 0; 0; 11] @ data ; 1087 + [11; 0; 0; 33; 0; 0; 29; 0; 0; 12] @ data @ [0; 0; 12] @ data ; 1088 + [11; 0; 0; 33; 0; 0; 31; 0; 0; 12] @ data @ [0; 0; 12] @ data ; 1089 + [11; 0; 0; 33; 0; 0; 30; 0; 0; 11] @ data @ [0; 0; 12] @ data 1090 + ] 1091 + 1092 + let bad_certificate_cstruct_data_parser xs _ = 1093 + let buf = list_to_cstruct xs in 1094 + Reader.(match parse_handshake buf with 1095 + | Ok (Core.Certificate cs) -> 1096 + (match Reader.parse_certificates cs with 1097 + | Ok _ -> assert_failure "bad certificate parser won" 1098 + | Error _ -> ()) 1099 + | _ -> assert_failure "should've been a certificate") 1100 + 1101 + let bad_certificate_cstruct_data_tests = 1102 + List.mapi 1103 + (fun i f -> "Parse bad certificate " ^ string_of_int i >:: bad_certificate_cstruct_data_parser f) 1104 + bad_certificate_cstruct_data 1105 + 1106 + let good_client_hellos = 1107 + (* I rolled the dice 16 times *) 1108 + let rnd = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 1109 + let rand = rnd @ rnd in 1110 + let client_random = list_to_cstruct rand in 1111 + Core.(let ch : client_hello = 1112 + { client_version = `TLS_1_2 ; 1113 + client_random ; 1114 + sessionid = None ; 1115 + ciphersuites = [] ; 1116 + extensions = []} 1117 + in 1118 + [ 1119 + (* versions *) 1120 + ([1; 0; 0; 38; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] , ch ) ; 1121 + ([1; 0; 0; 38; 3; 0] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] , { ch with client_version = `SSL_3 } ) ; 1122 + ([1; 0; 0; 38; 3; 1] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] , { ch with client_version = `TLS_1_0 } ) ; 1123 + ([1; 0; 0; 38; 3; 2] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] , { ch with client_version = `TLS_1_1 } ) ; 1124 + ([1; 0; 0; 38; 3; 4] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] , { ch with client_version = `TLS_1_3 } ) ; 1125 + ([1; 0; 0; 38; 3; 5] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] , { ch with client_version = `TLS_1_X 5 } ) ; 1126 + 1127 + (* well-formed compression (not available in higher layer) *) 1128 + ([1; 0; 0; 39; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 1; 0; (* exts *)] , ch ) ; 1129 + ([1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 2; 0; 1; (* exts *)] , ch ) ; 1130 + 1131 + (* ciphersuites *) 1132 + ([1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 2; 0; 0x0A; (* comp *) 0; (* exts *)] , { ch with ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] } ) ; 1133 + ([1; 0; 0; 42; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 4; 0; 0x0A; 0; 0x16; (* comp *) 0; (* exts *)] , { ch with ciphersuites = Packet.([TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA]) } ) ; 1134 + 1135 + (* ignore unknown ciphersuite *) 1136 + ([1; 0; 0; 42; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 4; 0; 0x0A; 0; 0x47; (* comp *) 0; (* exts *)] , { ch with ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] } ) ; 1137 + 1138 + (* ignore unknown compression method *) 1139 + ([1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 2; 0; 42; (* exts *)] , ch ) ; 1140 + 1141 + (* TODO: unknown extensions should be ignored (check again with rfc) *) 1142 + (* TODO: validate client_hello: 1143 + - non-empty ciphersuites 1144 + - no duplicated ciphersuites 1145 + - those required by protocol version should be in the list! 1146 + - no duplicated extensions 1147 + - no unsupported extensions (SignatureAlgorithms in TLS < 1.2) 1148 + - empty ServerName extension is useless 1149 + *) 1150 + 1151 + (* combine ciphersuite + compression *) 1152 + ([1; 0; 0; 44; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 4; 0; 0x0A; 0; 0x16; (* comp *) 2; 0; 1; (* exts *)] , { ch with ciphersuites = Packet.([TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA]) }) ; 1153 + 1154 + (* session id *) 1155 + ([1; 0; 0; 41; 3; 3] @ rand @ [(* session id *) 3; 1; 2; 3; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] , { ch with sessionid = Some (list_to_cstruct [1; 2; 3] ) } ) ; 1156 + 1157 + (* combine ciphersuite + compression + session id *) 1158 + ([1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 3; 1; 2; 3; (* cipher *) 0; 4; 0; 0x0A; 0; 0x16; (* comp *) 2; 0; 1; (* exts *)] , { ch with ciphersuites = Packet.([TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA]) ; sessionid = Some (list_to_cstruct [1; 2; 3]) }) ; 1159 + 1160 + 1161 + (* extensions *) 1162 + (* empty *) 1163 + ([1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 0] , ch ) ; 1164 + 1165 + (* some hostname *) 1166 + ([1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 0; 0; 8; 0; 6; 0; 0; 3; 102; 111; 111] , { ch with extensions = [make_hostname_ext "foo"] } ) ; 1167 + (* some other hostname *) 1168 + ([1; 0; 0; 59; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 19; 0; 0; 0; 15; 0; 13; 0; 0; 10; 102; 111; 111; 98; 97; 114; 46; 99; 111; 109] , { ch with extensions = [make_hostname_ext "foobar.com"] } ) ; 1169 + 1170 + (* max fragment length *) 1171 + ([1; 0; 0; 45; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 5; 0; 1; 0; 1; 3] , { ch with extensions = [`MaxFragmentLength Packet.TWO_11] } ) ; 1172 + 1173 + (* empty SupportedGroups *) 1174 + ([1; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 6; 0; 0xA; 0; 2; 0; 0] , { ch with extensions = [`SupportedGroups []] } ) ; 1175 + (* one supported group *) 1176 + ([1; 0; 0; 48; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 8; 0; 0xA; 0; 4; 0; 2; 0; 25] , { ch with extensions = [`SupportedGroups [Packet.SECP521R1]] } ) ; 1177 + (* two supported groups *) 1178 + ([1; 0; 0; 50; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 10; 0; 0xA; 0; 6; 0; 4; 0; 25; 0; 24] , { ch with extensions = [`SupportedGroups Packet.([SECP521R1; SECP384R1])] } ) ; 1179 + (* three supported groups, one unknown *) 1180 + ([1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 0xA; 0; 8; 0; 6; 0; 25; 0xFF; 0xFF; 0; 24] , { ch with extensions = [`SupportedGroups Packet.([SECP521R1; SECP384R1])] } ) ; 1181 + 1182 + (* secure renegotiation *) 1183 + ([1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0xFF; 1; 0; 3; 2; 1; 2] , { ch with extensions = [`SecureRenegotiation (list_to_cstruct [1;2])] } ) ; 1184 + 1185 + (* Padding *) 1186 + ([1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 21; 0; 3; 0; 0; 0] , { ch with extensions = [`Padding 3] } ) ; 1187 + 1188 + (* signature algorithm *) 1189 + ([1; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 6; 0; 13; 0; 2; 0; 0] , { ch with extensions = [`SignatureAlgorithms []] } ) ; 1190 + ([1; 0; 0; 48; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 8; 0; 13; 0; 4; 0; 2; 1; 1] , { ch with extensions = [`SignatureAlgorithms [`RSA_PKCS1_MD5]] } ) ; 1191 + ([1; 0; 0; 50; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 10; 0; 13; 0; 6; 0; 4; 2; 1; 1; 1] , { ch with extensions = [`SignatureAlgorithms [`RSA_PKCS1_SHA1; `RSA_PKCS1_MD5]] }) ; 1192 + (* unknown one *) 1193 + ([1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 13; 0; 8; 0; 6; 42; 42; 2; 1; 1; 1] , { ch with extensions = [`SignatureAlgorithms [`RSA_PKCS1_SHA1; `RSA_PKCS1_MD5]] } ) ; 1194 + 1195 + (* ALPN *) 1196 + ([1; 0; 0; 58; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 18; 0; 16; 0; 14; 0; 12; (* h2 *) 2; 104; 50; (* http/1.1*) 8; 104; 116; 116; 112; 47; 49; 46; 49] , { ch with extensions = [`ALPN ["h2"; "http/1.1"]] } ) ; 1197 + 1198 + (* combinations from the real world *) 1199 + ([0x01; (* hello *) 1200 + 0x00; 0x00; 0xaf; (* length *) 1201 + 0x03; 0x01; (* version *) 1202 + 0x7c; 0x53; 0x05; 0x72; 0x7a; 0x1b; 0x84; 0x70; 0x30; 0x89; 0xef; 0xad; 0xfb; 0x56; 0xc1; 0x3d; 0x73; 0x4b; 0xc7; 0xcb; 0x8c; 0xc8; 0x75; 0x43; 0x01; 0x12; 0x32; 0xd6; 0x74; 0x87; 0xcb; 0x18; (* random *) 1203 + 0x00; (* session id *) 1204 + 0x00; 0x68; (* ciphersuites *) 1205 + 0xc0; 0x14; 0xc0; 0x0a; 0xc0; 0x22; 0xc0; 0x21; 0x00; 0x39; 0x00; 0x38; 0x00; 0x88; 0x00; 0x87; 0xc0; 0x0f; 0xc0; 0x05; 0x00; 0x35; 0x00; 0x84; 0xc0; 0x12; 0xc0; 0x08; 0xc0; 0x1c; 0xc0; 0x1b; 0x00; 0x16; 0x00; 0x13; 0xc0; 0x0d; 0xc0; 0x03; 0x00; 0x0a; 0xc0; 0x13; 0xc0; 0x09; 0xc0; 0x1f; 0xc0; 0x1e; 0x00; 0x33; 0x00; 0x32; 0x00; 0x9a; 0x00; 0x99; 0x00; 0x45; 0x00; 0x44; 0xc0; 0x0e; 0xc0; 0x04; 0x00; 0x2f; 0x00; 0x96; 0x00; 0x41; 0x00; 0x07; 0xc0; 0x11; 0xc0; 0x07; 0xc0; 0x0c; 0xc0; 0x02; 0x00; 0x05; 0x00; 0x04; 0x00; 0x15; 0x00; 0x12; 0x00; 0x09; 0x00; 0x14; 0x00; 0x11; 0x00; 0x08; 0x00; 0x06; 0x00; 0x03; 0x00; 0xff; 1206 + 0x01; 0x00; (* compression *) 1207 + 0x00; 0x1e; (* extensions *) 1208 + 0x00; 0x0a; 0x00; 0x08; (* elliptic curves *) 1209 + 0x00; 0x06; 0x00; 0x19; 0x00; 0x18; 0x00; 0x17; 1210 + 0x00; 0x10; 0x00; 0x0e; 0x00; 0x0c; (* ALPN *) 1211 + 0x02; 0x68; 0x32; 1212 + 0x08; 0x68; 0x74; 0x74; 0x70; 0x2f; 0x31; 0x2e; 0x31 ] 1213 + (* 0x00; 0x23; 0x00; 0x00; (* sessionticket_tls *) 1214 + 0x00; 0x0f; 0x00; 0x01; 0x01 (* heartbeat *) *) , 1215 + { ch with 1216 + client_version = `TLS_1_0 ; 1217 + client_random = list_to_cstruct [0x7c; 0x53; 0x05; 0x72; 0x7a; 0x1b; 0x84; 0x70; 0x30; 0x89; 0xef; 0xad; 0xfb; 0x56; 0xc1; 0x3d; 0x73; 0x4b; 0xc7; 0xcb; 0x8c; 0xc8; 0x75; 0x43; 0x01; 0x12; 0x32; 0xd6; 0x74; 0x87; 0xcb; 0x18] ; 1218 + ciphersuites = Packet.([TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA; TLS_DHE_RSA_WITH_AES_256_CBC_SHA; TLS_RSA_WITH_AES_256_CBC_SHA; TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA; TLS_RSA_WITH_3DES_EDE_CBC_SHA; TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA; TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA; TLS_DHE_RSA_WITH_AES_128_CBC_SHA; TLS_RSA_WITH_AES_128_CBC_SHA; TLS_EMPTY_RENEGOTIATION_INFO_SCSV]); 1219 + extensions = [`SupportedGroups Packet.([SECP521R1; SECP384R1; SECP256R1]); 1220 + `ALPN ["h2"; "http/1.1"] ] } ) ; 1221 + 1222 + ( 1223 + [ 0x01; (* client hello *) 1224 + 0x00; 0x01; 0xc6; (* length *) 1225 + 0x03; 0x03; (* protocol version *) 1226 + 0xb7; 0x36; 0xeb; 0x21; 0xec; 0x81; 0x4d; 0x01; 0xfc; 0xf4; 0xe2; 0x06; 0x9a; 0x34; 0xb7; 0x21; 0xe1; 0x23; 0x6f; 0xbe; 0x50; 0xbf; 0xfe; 0x33; 0x9b; 0xc9; 0x5b; 0x20; 0x0e; 0x15; 0x02; 0x27; (* random *) 1227 + 0x00; (* session id *) 1228 + 0x00; 0xa0; (* ciphersuites *) 1229 + 0xc0; 0x30; 0xc0; 0x2c; 0xc0; 0x28; 0xc0; 0x24; 0xc0; 0x14; 0xc0; 0x0a; 0xc0; 0x22; 0xc0; 0x21; 0x00; 0xa3; 0x00; 0x9f; 0x00; 0x6b; 0x00; 0x6a; 0x00; 0x39; 0x00; 0x38; 0x00; 0x88; 0x00; 0x87; 0xc0; 0x32; 0xc0; 0x2e; 0xc0; 0x2a; 0xc0; 0x26; 0xc0; 0x0f; 0xc0; 0x05; 0x00; 0x9d; 0x00; 0x3d; 0x00; 0x35; 0x00; 0x84; 0xc0; 0x12; 0xc0; 0x08; 0xc0; 0x1c; 0xc0; 0x1b; 0x00; 0x16; 0x00; 0x13; 0xc0; 0x0d; 0xc0; 0x03; 0x00; 0x0a; 0xc0; 0x2f; 0xc0; 0x2b; 0xc0; 0x27; 0xc0; 0x23; 0xc0; 0x13; 0xc0; 0x09; 0xc0; 0x1f; 0xc0; 0x1e; 0x00; 0xa2; 0x00; 0x9e; 0x00; 0x67; 0x00; 0x40; 0x00; 0x33; 0x00; 0x32; 0x00; 0x9a; 0x00; 0x99; 0x00; 0x45; 0x00; 0x44; 0xc0; 0x31; 0xc0; 0x2d; 0xc0; 0x29; 0xc0; 0x25; 0xc0; 0x0e; 0xc0; 0x04; 0x00; 0x9c; 0x00; 0x3c; 0x00; 0x2f; 0x00; 0x96; 0x00; 0x41; 0x00; 0x07; 0xc0; 0x11; 0xc0; 0x07; 0xc0; 0x0c; 0xc0; 0x02; 0x00; 0x05; 0x00; 0x04; 0x00; 0x15; 0x00; 0x12; 0x00; 0x09; 0x00; 0x14; 0x00; 0x11; 0x00; 0x08; 0x00; 0x06; 0x00; 0x03; 0x00; 0xff; 1230 + 0x01; 0x00; (* compression *) 1231 + 0x00; 0xFD; (* extensions *) 1232 + 0x00; 0x0a; 0x00; 0x08; (* ec curves *) 1233 + 0x00; 0x06; 0x00; 0x19; 0x00; 0x18; 0x00; 0x17; 1234 + (* 0x00; 0x23; 0x00; 0x00; *) 1235 + 0x00; 0x0d; 0x00; 0x0c; (* signature algorithms *) 1236 + 0x00; 0x0a; 0x06; 0x01; 0x05; 0x01; 0x04; 0x01; 0x03; 0x01; 0x02; 0x01; 1237 + 0x00; 0x15; 0x00; 0xcb; (* padding *) 1238 + 0x00; 0x00; 1239 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1240 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1241 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1242 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1243 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1244 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1245 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1246 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1247 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1248 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1249 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1250 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1251 + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 1252 + 0x00; 0x10; 0x00; 0x0e; 0x00; 0x0c; (* ALPN *) 1253 + 0x02; 0x68; 0x32; 1254 + 0x08; 0x68; 0x74; 0x74; 0x70; 0x2f; 0x31; 0x2e; 0x31 ], 1255 + { ch with 1256 + client_version = `TLS_1_2 ; 1257 + client_random = list_to_cstruct [0xb7; 0x36; 0xeb; 0x21; 0xec; 0x81; 0x4d; 0x01; 0xfc; 0xf4; 0xe2; 0x06; 0x9a; 0x34; 0xb7; 0x21; 0xe1; 0x23; 0x6f; 0xbe; 0x50; 0xbf; 0xfe; 0x33; 0x9b; 0xc9; 0x5b; 0x20; 0x0e; 0x15; 0x02; 0x27] ; 1258 + ciphersuites = Packet.([TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384; TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384; TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA; TLS_DHE_RSA_WITH_AES_256_GCM_SHA384; TLS_DHE_RSA_WITH_AES_256_CBC_SHA256; TLS_DHE_RSA_WITH_AES_256_CBC_SHA; TLS_RSA_WITH_AES_256_GCM_SHA384; TLS_RSA_WITH_AES_256_CBC_SHA256; TLS_RSA_WITH_AES_256_CBC_SHA; TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA; TLS_RSA_WITH_3DES_EDE_CBC_SHA; TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA; TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA; TLS_DHE_RSA_WITH_AES_128_GCM_SHA256; TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; TLS_DHE_RSA_WITH_AES_128_CBC_SHA; TLS_RSA_WITH_AES_128_GCM_SHA256; TLS_RSA_WITH_AES_128_CBC_SHA256; TLS_RSA_WITH_AES_128_CBC_SHA; TLS_EMPTY_RENEGOTIATION_INFO_SCSV]) ; 1259 + extensions = [`SupportedGroups Packet.([SECP521R1; SECP384R1; SECP256R1]); 1260 + `SignatureAlgorithms 1261 + [`RSA_PKCS1_SHA512 ; 1262 + `RSA_PKCS1_SHA384 ; 1263 + `RSA_PKCS1_SHA256 ; 1264 + `RSA_PKCS1_SHA224 ; 1265 + `RSA_PKCS1_SHA1 ] ; 1266 + `Padding 203 ; 1267 + `ALPN ["h2"; "http/1.1"] ] } ); 1268 + 1269 + 1270 + ( [ 0x01; (* client hello *) 1271 + 0x00; 0x00; 0x74; (* length *) 1272 + 0x03; 0x04; (* version *) 1273 + 0xf1; 0xb2; 0x50; 0x16; 0x4b; 0x77; 0x50; 0xb3; 0xdc; 0xcb; 0x1c; 0x6a; 0xae; 0x1a; 0x94; 0x87; 1274 + 0xc4; 0x17; 0xbb; 0xa4; 0xf7; 0x92; 0xf8; 0x16; 0x56; 0x12; 0x03; 0x38; 0x1e; 0xe5; 0xc1; 0xae; (* client random *) 1275 + 0x00; (* session id *) 1276 + 0x00; 0x10; 0x00; 0x35; 0x00; 0x39; 0x00; 0x2f; 0x00; 0x33; 0x00; 0x16; 0x00; 0x0a; 0x00; 0x05; 0x00; 0x04; (* ciphersuites *) 1277 + 0x01; 0x00; (* compression *) 1278 + 0x00; 0x3b; (* extensions *) 1279 + 0xff; 0x01; 0x00; 0x01; 0x00; (* secure reneg *) 1280 + 0x00; 0x00; 0x00; 0x10; 0x00; 0x0e; 0x00; 0x00; 0x0b; 0x65; 0x78; 0x61; 0x6d; 0x70; 0x6c; 0x65; 0x2e; 0x63; 0x6f; 0x6d; (* SNI example.com *) 1281 + 0x00; 0x0d; 0x00; 0x0c; 0x00; 0x0a; 0x06; 0x01; 0x05; 0x01; 0x04; 0x01; 0x02; 0x01; 0x01; 0x01; (* SignatureAlgorithms *) 1282 + 0x00; 0x10; 0x00; 0x0e; 0x00; 0x0c; (* ALPN *) 1283 + 0x02; 0x68; 0x32; 1284 + 0x08; 0x68; 0x74; 0x74; 0x70; 0x2f; 0x31; 0x2e; 0x31 1285 + ], 1286 + { ch with client_version = `TLS_1_3 ; 1287 + client_random = list_to_cstruct [ 0xf1; 0xb2; 0x50; 0x16; 0x4b; 0x77; 0x50; 0xb3; 0xdc; 0xcb; 0x1c; 0x6a; 0xae; 0x1a; 0x94; 0x87; 0xc4; 0x17; 0xbb; 0xa4; 0xf7; 0x92; 0xf8; 0x16; 0x56; 0x12; 0x03; 0x38; 0x1e; 0xe5; 0xc1; 0xae ] ; 1288 + ciphersuites = Packet.([TLS_RSA_WITH_AES_256_CBC_SHA ; TLS_DHE_RSA_WITH_AES_256_CBC_SHA ; TLS_RSA_WITH_AES_128_CBC_SHA ; TLS_DHE_RSA_WITH_AES_128_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_3DES_EDE_CBC_SHA]) ; 1289 + extensions = [ `SecureRenegotiation "" ; 1290 + make_hostname_ext "example.com" ; 1291 + `SignatureAlgorithms 1292 + [`RSA_PKCS1_SHA512 ; 1293 + `RSA_PKCS1_SHA384 ; 1294 + `RSA_PKCS1_SHA256 ; 1295 + `RSA_PKCS1_SHA1 ; 1296 + `RSA_PKCS1_MD5] ; 1297 + `ALPN ["h2"; "http/1.1"] ] 1298 + } 1299 + ) 1300 + ]) 1301 + 1302 + let cmp_client_hellos ch ch' = 1303 + let open Core in 1304 + assert_equal ch.client_version ch'.client_version ; 1305 + assert_cs_eq ch.client_random ch'.client_random ; 1306 + assert_sessionid_equal ch.sessionid ch'.sessionid ; 1307 + assert_lists_eq assert_equal ch.ciphersuites ch'.ciphersuites ; 1308 + assert_lists_eq assert_client_extension_equal ch.extensions ch'.extensions 1309 + 1310 + let good_client_hellos_parser (xs, res) _ = 1311 + let buf = list_to_cstruct xs in 1312 + match Reader.parse_handshake buf with 1313 + | Ok (Core.ClientHello ch) -> cmp_client_hellos ch res 1314 + | _ -> assert_failure "handshake client hello parser failed" 1315 + 1316 + let good_client_hellos_tests = 1317 + List.mapi 1318 + (fun i f -> "Parse good client hello " ^ string_of_int i >:: good_client_hellos_parser f) 1319 + good_client_hellos 1320 + 1321 + let bad_client_hellos = 1322 + (* I rolled the dice 16 times *) 1323 + let rnd = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 1324 + let rand = rnd @ rnd in 1325 + [ 1326 + (* versions *) 1327 + [1; 0; 0; 38; 4; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1328 + (* invalid length *) 1329 + [1; 0; 0; 39; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1330 + (* should be broken as well due to missing compression_algos *) 1331 + [1; 0; 0; 38; 3; 3] @ rand @ [(* session id *) 1; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1332 + 1333 + (* ciphersuites *) 1334 + [1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 1; 0; 0; (* comp *) 0; (* exts *)] ; 1335 + [1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 3; 0; 0; (* comp *) 0; (* exts *)] ; 1336 + [1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 1; 3; 0; 0; (* comp *) 0; (* exts *)] ; 1337 + 1338 + (* extensions *) 1339 + (* empty *) 1340 + [1; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 1] ; 1341 + 1342 + (* some hostname *) 1343 + [1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 0; 0; 8; 0; 6; 0; 0; 4; 102; 111; 111] ; 1344 + [1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 0; 0; 8; 0; 6; 0; 0; 4; 102; 111; 111; 111] ; 1345 + [1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 0; 0; 8; 0; 7; 0; 0; 4; 102; 111; 111; 111] ; 1346 + [1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 0; 0; 9; 0; 7; 0; 0; 4; 102; 111; 111; 111] ; 1347 + [1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 13; 0; 0; 0; 9; 0; 7; 0; 0; 4; 102; 111; 111; 111] ; 1348 + [1; 0; 0; 52; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 12; 0; 0; 0; 8; 0; 5; 0; 0; 2; 102; 111; 111] ; 1349 + 1350 + (* multiple hostnames - legal in RFC, not accepted by any implementation *) 1351 + [1; 0; 0; 58; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 18; 0; 0; 0; 14; 0; 12; 0; 0; 3; 102; 111; 111; 0; 0; 3; 98; 97; 114] ; 1352 + 1353 + (* empty SupportedGroups *) 1354 + [1; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 6; 0; 0xA; 0; 1; 0; 0] ; 1355 + [1; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 5; 0; 0xA; 0; 2; 0; 0] ; 1356 + [1; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 6; 0; 0xA; 0; 2; 0; 1] ; 1357 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 0xA; 0; 3; 0; 1; 0] ; 1358 + [1; 0; 0; 50; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 10; 0; 0xA; 0; 6; 0; 2; 0; 25; 0; 20] ; 1359 + 1360 + (* secure renegotiation *) 1361 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0xFF; 1; 0; 5; 2; 1; 2] ; 1362 + [1; 0; 0; 49; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0xFF; 1; 0; 5; 2; 1; 2; 3; 4] ; 1363 + [1; 0; 0; 49; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 9; 0xFF; 1; 0; 3; 2; 1; 2; 3; 4] ; 1364 + [1; 0; 0; 49; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 9; 0xFF; 1; 0; 5; 10; 1; 2; 3; 4] ; 1365 + [1; 0; 0; 49; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 9; 0xFF; 1; 0; 5; 2; 1; 2; 3; 4] ; 1366 + 1367 + (* max fragment length *) 1368 + [1; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 6; 0; 1; 0; 2; 3; 4] ; 1369 + [1; 0; 0; 44; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 4; 0; 1; 0; 0] ; 1370 + [1; 0; 0; 45; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 5; 0; 1; 0; 1; 42] ; 1371 + 1372 + (* Padding *) 1373 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 21; 0; 3; 1; 2; 3] ; 1374 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 21; 0; 5; 0; 0; 0] ; 1375 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 9; 0; 21; 0; 5; 0; 0; 0] ; 1376 + [1; 0; 0; 49; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 9; 0; 21; 0; 5; 0; 0; 0] ; 1377 + [1; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 21; 0; 3; 0; 0; 0] ; 1378 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 21; 0; 2; 0; 0; 0] ; 1379 + 1380 + (* sig hash *) 1381 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 13; 0; 3; 0; 1; 0] ; 1382 + [1; 0; 0; 47; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 7; 0; 13; 0; 3; 0; 0; 0] ; 1383 + ] 1384 + 1385 + let bad_client_hello_parser xs _ = 1386 + let buf = list_to_cstruct xs in 1387 + match Reader.parse_handshake buf with 1388 + | Ok _ -> assert_failure "bad client hello parser won" 1389 + | Error _ -> () 1390 + 1391 + let bad_client_hello_tests = 1392 + List.mapi 1393 + (fun i f -> "Parse bad client hello " ^ string_of_int i >:: bad_client_hello_parser f) 1394 + bad_client_hellos 1395 + 1396 + let good_server_hellos = 1397 + (* I rolled the dice 16 times *) 1398 + let rnd = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 1399 + let rand = rnd @ rnd in 1400 + let server_random = list_to_cstruct rand in 1401 + Core.(let sh : server_hello = 1402 + { server_version = `TLS_1_2 ; 1403 + server_random ; 1404 + sessionid = None ; 1405 + ciphersuite = `RSA_WITH_AES_128_CCM ; 1406 + extensions = []} 1407 + in 1408 + [ 1409 + (* versions *) 1410 + ([2; 0; 0; 38; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] , sh ) ; 1411 + ([2; 0; 0; 38; 3; 1] @ rand @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] , { sh with server_version = `TLS_1_0 } ) ; 1412 + ([2; 0; 0; 38; 3; 2] @ rand @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] , { sh with server_version = `TLS_1_1 } ) ; 1413 + 1414 + (* session id *) 1415 + ([2; 0; 0; 41; 3; 3] @ rand @ [(* session id *) 3; 1; 2; 3; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] , { sh with sessionid = Some (list_to_cstruct [1; 2; 3]) } ) ; 1416 + 1417 + (* ciphersuite *) 1418 + ([2; 0; 0; 38; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0xc0; 0x9d; (* comp *) 0; (* exts *)] , { sh with ciphersuite = `RSA_WITH_AES_256_CCM } ) ; 1419 + 1420 + (* extensions *) 1421 + (* empty *) 1422 + ([2; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 0] , sh ) ; 1423 + 1424 + (* empty hostname *) 1425 + ([2; 0; 0; 44; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 4; 0; 0; 0; 0] , { sh with extensions = [`Hostname] } ) ; 1426 + 1427 + (* ALPN *) 1428 + ([2; 0; 0; 49; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 9; 0; 16; 0; 5; 0; 3; 2; 104; 50] , { sh with extensions = [`ALPN "h2"] } ) ; 1429 + 1430 + (* TODO: chosen ciphersuite must not be renegotiation (0x00ff) *) 1431 + 1432 + (* TODO: validation of extensions 1433 + - ServerName, if present, should be None 1434 + - Padding is not allowed 1435 + - EC stuff must be present if EC ciphersuite chosen 1436 + - protocol version dependencies (SignatureAlgorithm) 1437 + - no duplicates! 1438 + - only those which are in a client hello are allowed 1439 + - is there an ordering? 1440 + *) 1441 + ( [ 1442 + 0x02; (* typ *) 1443 + 0x00; 0x00; 0x5A; (* len *) 1444 + 0x03; 0x03; (* version *) 1445 + 0x53; 0x66; 0x2d; 0xf0; 0x1b; 0x61; 0x55; 0x8f; 0x74; 0x2a; 0xbf; 0xf4; 0x99; 0x86; 0x30; 0x99; 0x32; 0xe4; 0xd0; 0x1e; 0x2b; 0xa9; 0x2e; 0x86; 0x7b; 0xeb; 0x03; 0x00; 0xf9; 0x11; 0x3e; 0xc5; (* random *) 1446 + 0x20; (* session ID *) 1447 + 0xd1; 0x54; 0xd9; 0x05; 0x61; 0x41; 0x53; 0x33; 0xb2; 0xf0; 0x13; 0x78; 0x1a; 0x17; 0xb3; 0x1d; 0x09; 0xf6; 0x59; 0x70; 0xfe; 0x5d; 0x58; 0x22; 0xfa; 0x8c; 0x5c; 0x89; 0xe9; 0xa2; 0xb4; 0x70; 1448 + 0x00; 0x2f; (* cipher *) 1449 + 0x00; (* compression *) 1450 + 0x00; 0x12; (* extensions *) 1451 + 0x00; 0x00; 0x00; 0x00; (* servername *) 1452 + 0xff; 0x01; 0x00; 0x01; 0x00; (* secure renegotiation *) 1453 + 0x00; 0x10; 0x00; 0x05; 0x00; 0x03; (* ALPN *) 1454 + 0x02; 0x68; 0x32 1455 + ], { sh with 1456 + ciphersuite = `RSA_WITH_AES_128_CBC_SHA ; 1457 + server_random = list_to_cstruct [ 0x53; 0x66; 0x2d; 0xf0; 0x1b; 0x61; 0x55; 0x8f; 0x74; 0x2a; 0xbf; 0xf4; 0x99; 0x86; 0x30; 0x99; 0x32; 0xe4; 0xd0; 0x1e; 0x2b; 0xa9; 0x2e; 0x86; 0x7b; 0xeb; 0x03; 0x00; 0xf9; 0x11; 0x3e; 0xc5 ] ; 1458 + sessionid = Some (list_to_cstruct [ 0xd1; 0x54; 0xd9; 0x05; 0x61; 0x41; 0x53; 0x33; 0xb2; 0xf0; 0x13; 0x78; 0x1a; 0x17; 0xb3; 0x1d; 0x09; 0xf6; 0x59; 0x70; 0xfe; 0x5d; 0x58; 0x22; 0xfa; 0x8c; 0x5c; 0x89; 0xe9; 0xa2; 0xb4; 0x70 ]) ; 1459 + extensions = [`Hostname; 1460 + `SecureRenegotiation ""; 1461 + `ALPN "h2"] }) ; 1462 + 1463 + ( [ 1464 + 0x02; 1465 + 0x00; 0x00; 0x51; 1466 + 0x03; 0x03; 1467 + 0x53; 0x66; 0x2f; 0xb7; 0x35; 0x3a; 0x42; 0xee; 0x1c; 0xe6; 0xed; 0x63; 0x8a; 0x1d; 0x3d; 0xb3; 0x71; 0x9c; 0xf5; 0x64; 0x45; 0xc5; 0xe9; 0xf4; 0x11; 0x8b; 0x9f; 0x41; 0x5a; 0x5f; 0xf1; 0xf6; 1468 + 0x20; 1469 + 0xdf; 0xe1; 0x09; 0x8a; 0x42; 0xf0; 0x25; 0xc7; 0xbd; 0xe5; 0xe9; 0x02; 0x6a; 0x03; 0xaf; 0xb4; 0x70; 0x80; 0xe9; 0x2f; 0x07; 0x3f; 0x53; 0xd3; 0xc8; 0x97; 0x3f; 0xc4; 0x44; 0x23; 0xf5; 0x94; 1470 + 0x00; 0x2f; 1471 + 0x00; 1472 + 0x00; 0x09; 1473 + 0x00; 0x00; 0x00; 0x00; 1474 + 0xff; 0x01; 0x00; 0x01; 0x00 ], 1475 + { sh with 1476 + ciphersuite = `RSA_WITH_AES_128_CBC_SHA ; 1477 + server_random = list_to_cstruct [ 0x53; 0x66; 0x2f; 0xb7; 0x35; 0x3a; 0x42; 0xee; 0x1c; 0xe6; 0xed; 0x63; 0x8a; 0x1d; 0x3d; 0xb3; 0x71; 0x9c; 0xf5; 0x64; 0x45; 0xc5; 0xe9; 0xf4; 0x11; 0x8b; 0x9f; 0x41; 0x5a; 0x5f; 0xf1; 0xf6 ] ; 1478 + sessionid = Some (list_to_cstruct [ 0xdf; 0xe1; 0x09; 0x8a; 0x42; 0xf0; 0x25; 0xc7; 0xbd; 0xe5; 0xe9; 0x02; 0x6a; 0x03; 0xaf; 0xb4; 0x70; 0x80; 0xe9; 0x2f; 0x07; 0x3f; 0x53; 0xd3; 0xc8; 0x97; 0x3f; 0xc4; 0x44; 0x23; 0xf5; 0x94 ] ) ; 1479 + extensions = [`Hostname; 1480 + `SecureRenegotiation ""] }) ; 1481 + 1482 + ]) 1483 + 1484 + let cmp_server_hellos sh sh' = 1485 + let open Core in 1486 + assert_equal sh.server_version sh'.server_version ; 1487 + assert_cs_eq sh.server_random sh'.server_random ; 1488 + assert_sessionid_equal sh.sessionid sh'.sessionid ; 1489 + assert_equal sh.ciphersuite sh'.ciphersuite ; 1490 + assert_lists_eq assert_server_extension_equal sh.extensions sh'.extensions 1491 + 1492 + let good_server_hellos_parser (xs, res) _ = 1493 + let buf = list_to_cstruct xs in 1494 + match Reader.parse_handshake buf with 1495 + | Ok (Core.ServerHello sh) -> cmp_server_hellos sh res 1496 + | _ -> assert_failure "handshake server hello parser failed" 1497 + 1498 + let good_server_hellos_tests = 1499 + List.mapi 1500 + (fun i f -> "Parse good server hello " ^ string_of_int i >:: good_server_hellos_parser f) 1501 + good_server_hellos 1502 + 1503 + let bad_server_hellos = 1504 + (* I rolled the dice 16 times *) 1505 + let rnd = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 1506 + let rand = rnd @ rnd in 1507 + [ 1508 + [2; 0; 0; 38; 3; 0] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1509 + [2; 0; 0; 38; 3; 4] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1510 + 1511 + [2; 0; 0; 30; 4; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1512 + [2; 0; 0; 38; 4; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1513 + [2; 0; 0; 44; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1514 + 1515 + [2; 0; 0; 38; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0xFF; 0xFF; (* comp *) 0; (* exts *)] ; 1516 + [2; 0; 0; 38; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 42; (* exts *)] ; 1517 + 1518 + (* session id *) 1519 + [2; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 3; 1; 2; (* cipher *) 0; 0; (* comp *) 0; (* exts *)] ; 1520 + 1521 + (* extensions *) 1522 + (* empty *) 1523 + [2; 0; 0; 40; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 1] ; 1524 + [2; 0; 0; 41; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 1] ; 1525 + [2; 0; 0; 41; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 1; 0] ; 1526 + 1527 + (* ALPN ext with a list of protocols *) 1528 + [2; 0; 0; 46; 3; 3] @ rand @ [(* session id *) 0; (* cipher *) 0; 0; (* comp *) 0; (* exts *) 0; 18; 0; 16; 0; 8; 0; 6; 3; 0x41; 0x41; 3; 0x42; 0x42] ; 1529 + ] 1530 + 1531 + let bad_server_hellos_parser xs _ = 1532 + let buf = list_to_cstruct xs in 1533 + match Reader.parse_handshake buf with 1534 + | Ok _ -> assert_failure "handshake server hello parser succeeded" 1535 + | Error _ -> () 1536 + 1537 + let bad_server_hellos_tests = 1538 + List.mapi 1539 + (fun i f -> "Parse bad server hello " ^ string_of_int i >:: bad_server_hellos_parser f) 1540 + bad_server_hellos 1541 + 1542 + let reader_tests = 1543 + any_version_tests @ version_tests @ 1544 + good_records_tests @ 1545 + good_alert_tests @ bad_alerts_tests @ 1546 + good_dh_params_tests @ bad_dh_params_tests @ 1547 + good_digitally_signed_1_2_tests @ bad_digitally_signed_1_2_tests @ 1548 + good_digitally_signed_tests @ bad_digitally_signed_tests @ 1549 + good_handshake_hdr_tests @ 1550 + good_handshake_no_data_tests @ bad_handshake_no_data_tests @ 1551 + good_handshake_cstruct_data_tests @ bad_handshake_cstruct_data_tests @ bad_certificate_cstruct_data_tests @ 1552 + good_client_hellos_tests @ bad_client_hello_tests @ 1553 + good_server_hellos_tests @ bad_server_hellos_tests
+439
vendor/opam/tls/tests/readerwritertests.ml
··· 1 + open Tls 2 + open OUnit2 3 + open Testlib 4 + 5 + let readerwriter_version v _ = 6 + let buf = Writer.assemble_protocol_version v in 7 + match Reader.parse_version buf with 8 + | Ok ver -> 9 + assert_equal v ver ; 10 + (* lets get crazy and do it one more time *) 11 + let buf' = Writer.assemble_protocol_version v in 12 + (match Reader.parse_version buf' with 13 + | Ok ver' -> assert_equal v ver' 14 + | Error _ -> assert_failure "read and write version broken") 15 + | Error _ -> assert_failure "read and write version broken" 16 + 17 + let version_tests = 18 + [ "ReadWrite version TLS-1.0" >:: readerwriter_version `TLS_1_0 ; 19 + "ReadWrite version TLS-1.1" >:: readerwriter_version `TLS_1_1 ; 20 + "ReadWrite version TLS-1.2" >:: readerwriter_version `TLS_1_2 ] 21 + 22 + let readerwriter_header (v, ct, cs) _ = 23 + let buf = Writer.assemble_hdr v (ct, cs) in 24 + match Reader.parse_record buf with 25 + | Ok (`Record ((hdr, payload), f)) -> 26 + let open Core in 27 + assert_equal 0 (String.length f) ; 28 + assert_equal (v :> tls_any_version) hdr.version ; 29 + assert_equal ct hdr.content_type ; 30 + assert_cs_eq cs payload ; 31 + let buf' = Writer.assemble_hdr v (hdr.content_type, payload) in 32 + (match Reader.parse_record buf' with 33 + | Ok (`Record ((hdr, payload), f)) -> 34 + assert_equal 0 (String.length f) ; 35 + assert_equal (v :> tls_any_version) hdr.version ; 36 + assert_equal ct hdr.content_type ; 37 + assert_cs_eq cs payload ; 38 + | _ -> assert_failure "inner header broken") 39 + | _ -> assert_failure "header broken" 40 + 41 + let header_tests = 42 + let a = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 43 + [ "ReadWrite header" >:: readerwriter_header (`TLS_1_0, Packet.HANDSHAKE, a) ; 44 + "ReadWrite header" >:: readerwriter_header (`TLS_1_1, Packet.HANDSHAKE, a) ; 45 + "ReadWrite header" >:: readerwriter_header (`TLS_1_2, Packet.HANDSHAKE, a) ; 46 + 47 + "ReadWrite header" >:: readerwriter_header (`TLS_1_0, Packet.APPLICATION_DATA, a) ; 48 + "ReadWrite header" >:: readerwriter_header (`TLS_1_1, Packet.APPLICATION_DATA, a) ; 49 + "ReadWrite header" >:: readerwriter_header (`TLS_1_2, Packet.APPLICATION_DATA, a) ; 50 + 51 + "ReadWrite header" >:: readerwriter_header (`TLS_1_0, Packet.CHANGE_CIPHER_SPEC, a) ; 52 + "ReadWrite header" >:: readerwriter_header (`TLS_1_1, Packet.CHANGE_CIPHER_SPEC, a) ; 53 + "ReadWrite header" >:: readerwriter_header (`TLS_1_2, Packet.CHANGE_CIPHER_SPEC, a) ; 54 + 55 + "ReadWrite header" >:: readerwriter_header (`TLS_1_0, Packet.ALERT, a) ; 56 + "ReadWrite header" >:: readerwriter_header (`TLS_1_1, Packet.ALERT, a) ; 57 + "ReadWrite header" >:: readerwriter_header (`TLS_1_2, Packet.ALERT, a) ; 58 + ] 59 + 60 + let readerwriter_alert (lvl, typ) _ = 61 + let buf, expl = match lvl with 62 + | None -> (Writer.assemble_alert typ, Packet.FATAL) 63 + | Some l -> (Writer.assemble_alert ~level:l typ, l) 64 + in 65 + (match Reader.parse_alert buf with 66 + | Ok (l', t') -> 67 + assert_equal expl l' ; 68 + assert_equal typ t' ; 69 + (* lets get crazy and do it one more time *) 70 + let buf' = Writer.assemble_alert ~level:l' t' in 71 + (match Reader.parse_alert buf' with 72 + | Ok (l'', t'') -> assert_equal expl l'' ; assert_equal typ t'' 73 + | Error _ -> assert_failure "inner read and write alert broken") 74 + | Error _ -> assert_failure "read and write alert broken") 75 + 76 + let rw_alert_tests = Packet.([ 77 + ( None, CLOSE_NOTIFY ) ; 78 + ( None, UNEXPECTED_MESSAGE ) ; 79 + ( None, BAD_RECORD_MAC ) ; 80 + ( None, RECORD_OVERFLOW ) ; 81 + ( None, HANDSHAKE_FAILURE ) ; 82 + ( None, BAD_CERTIFICATE ) ; 83 + ( None, CERTIFICATE_EXPIRED ) ; 84 + ( None, DECODE_ERROR ) ; 85 + ( None, PROTOCOL_VERSION ) ; 86 + ( None, UNSUPPORTED_EXTENSION ) ; 87 + ( None, UNRECOGNIZED_NAME ) ; 88 + ( None, NO_APPLICATION_PROTOCOL ) ; 89 + 90 + ( Some FATAL, CLOSE_NOTIFY ) ; 91 + ( Some FATAL, UNEXPECTED_MESSAGE ) ; 92 + ( Some FATAL, BAD_RECORD_MAC ) ; 93 + ( Some FATAL, RECORD_OVERFLOW ) ; 94 + ( Some FATAL, HANDSHAKE_FAILURE ) ; 95 + ( Some FATAL, BAD_CERTIFICATE ) ; 96 + ( Some FATAL, CERTIFICATE_EXPIRED ) ; 97 + ( Some FATAL, DECODE_ERROR ) ; 98 + ( Some FATAL, PROTOCOL_VERSION ) ; 99 + ( Some FATAL, UNSUPPORTED_EXTENSION ) ; 100 + ( Some FATAL, UNRECOGNIZED_NAME ) ; 101 + ( Some FATAL, NO_APPLICATION_PROTOCOL ) ; 102 + 103 + ( Some WARNING, CLOSE_NOTIFY ) ; 104 + (* ( Some WARNING, UNEXPECTED_MESSAGE ) ; 105 + ( Some WARNING, BAD_RECORD_MAC ) ; 106 + ( Some WARNING, DECRYPTION_FAILED ) ; 107 + ( Some WARNING, RECORD_OVERFLOW ) ; 108 + ( Some WARNING, DECOMPRESSION_FAILURE ) ; 109 + ( Some WARNING, HANDSHAKE_FAILURE ) ; *) 110 + ( Some FATAL, BAD_CERTIFICATE ) ; 111 + ( Some FATAL, CERTIFICATE_EXPIRED ) ; 112 + (* ( Some WARNING, UNKNOWN_CA ) ; 113 + ( Some WARNING, ACCESS_DENIED ) ; 114 + ( Some WARNING, DECODE_ERROR ) ; 115 + ( Some WARNING, DECRYPT_ERROR ) ; *) 116 + (* ( Some WARNING, PROTOCOL_VERSION ) ; 117 + ( Some WARNING, INSUFFICIENT_SECURITY ) ; 118 + ( Some WARNING, INTERNAL_ERROR ) ; *) 119 + ( Some WARNING, USER_CANCELED ) ; 120 + ( Some WARNING, NO_RENEGOTIATION ) ; 121 + (* ( Some WARNING, UNSUPPORTED_EXTENSION ) ; *) 122 + ( Some FATAL, UNRECOGNIZED_NAME ) ; 123 + ]) 124 + 125 + let rw_alert_tests = 126 + List.mapi 127 + (fun i f -> "RW alert " ^ string_of_int i >:: readerwriter_alert f) 128 + rw_alert_tests 129 + 130 + let assert_dh_eq a b = 131 + Core.(assert_cs_eq a.dh_p b.dh_p) ; 132 + Core.(assert_cs_eq a.dh_g b.dh_g) ; 133 + Core.(assert_cs_eq a.dh_Ys b.dh_Ys) 134 + 135 + let readerwriter_dh_params params _ = 136 + let buf = Writer.assemble_dh_parameters params in 137 + match Reader.parse_dh_parameters buf with 138 + | Ok (p, raw, rst) -> 139 + assert_equal (String.length rst) 0 ; 140 + assert_dh_eq p params ; 141 + assert_equal buf raw ; 142 + (* lets get crazy and do it one more time *) 143 + let buf' = Writer.assemble_dh_parameters p in 144 + (match Reader.parse_dh_parameters buf' with 145 + | Ok (p', raw', rst') -> 146 + assert_equal (String.length rst') 0 ; 147 + assert_dh_eq p' params ; 148 + assert_equal buf raw' ; 149 + | Error _ -> assert_failure "inner read and write dh params broken") 150 + | Error _ -> assert_failure "read and write dh params broken" 151 + 152 + let rw_dh_params = 153 + let a = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 154 + let emp = list_to_cstruct [] in 155 + Core.([ 156 + { dh_p = emp ; dh_g = emp ; dh_Ys = emp } ; 157 + { dh_p = a ; dh_g = emp ; dh_Ys = emp } ; 158 + { dh_p = emp ; dh_g = a ; dh_Ys = emp } ; 159 + { dh_p = emp ; dh_g = emp ; dh_Ys = a } ; 160 + { dh_p = a ^ a ; dh_g = a ^ a ; dh_Ys = a ^ a } ; 161 + ]) 162 + 163 + let rw_dh_tests = 164 + List.mapi 165 + (fun i f -> "RW dh_param " ^ string_of_int i >:: readerwriter_dh_params f) 166 + rw_dh_params 167 + 168 + let readerwriter_digitally_signed params _ = 169 + let buf = Writer.assemble_digitally_signed params in 170 + match Reader.parse_digitally_signed buf with 171 + | Ok params' -> 172 + assert_cs_eq params params' ; 173 + (* lets get crazy and do it one more time *) 174 + let buf' = Writer.assemble_digitally_signed params' in 175 + (match Reader.parse_digitally_signed buf' with 176 + | Ok params'' -> assert_cs_eq params params'' 177 + | Error _ -> assert_failure "inner read and write digitally signed broken") 178 + | Error _ -> assert_failure "read and write digitally signed broken" 179 + 180 + let rw_ds_params = 181 + let a = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 182 + let emp = list_to_cstruct [] in 183 + [ a ; a ^ a ; emp ; emp ^ a ] 184 + 185 + let rw_ds_tests = 186 + List.mapi 187 + (fun i f -> "RW digitally signed " ^ string_of_int i >:: readerwriter_digitally_signed f) 188 + rw_ds_params 189 + 190 + let readerwriter_digitally_signed_1_2 (sigalg, params) _ = 191 + let buf = Writer.assemble_digitally_signed_1_2 sigalg params in 192 + match Reader.parse_digitally_signed_1_2 buf with 193 + | Ok (sigalg', params') -> 194 + assert_equal sigalg sigalg' ; 195 + assert_cs_eq params params' ; 196 + (* lets get crazy and do it one more time *) 197 + let buf' = Writer.assemble_digitally_signed_1_2 sigalg' params' in 198 + (match Reader.parse_digitally_signed_1_2 buf' with 199 + | Ok (sigalg'', params'') -> 200 + assert_equal sigalg sigalg'' ; 201 + assert_cs_eq params params'' 202 + | Error _ -> assert_failure "inner read and write digitally signed 1.2 broken") 203 + | Error _ -> assert_failure "read and write digitally signed 1.2 broken" 204 + 205 + let rec cartesian_product f a b = 206 + match b with 207 + | [] -> [] 208 + | e::rt -> (List.map (fun x -> f x e) a) @ (cartesian_product f a rt) 209 + 210 + let rw_ds_1_2_params = 211 + let a = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 212 + let emp = list_to_cstruct [] in 213 + let cs = [ a ; a ^ a ; emp ; emp ^ a ] in 214 + let sig_algs = [ 215 + `RSA_PKCS1_MD5 ; `RSA_PKCS1_SHA1 ; `RSA_PKCS1_SHA224 ; `RSA_PKCS1_SHA256 ; 216 + `RSA_PKCS1_SHA384 ; `RSA_PKCS1_SHA512 ; 217 + `RSA_PSS_RSAENC_SHA256 ; `RSA_PSS_RSAENC_SHA384 ; `RSA_PSS_RSAENC_SHA512 218 + ] in 219 + cartesian_product (fun sigalg c -> (sigalg, c)) sig_algs cs 220 + 221 + let rw_ds_1_2_tests = 222 + List.mapi 223 + (fun i f -> "RW digitally signed 1.2 " ^ string_of_int i >:: readerwriter_digitally_signed_1_2 f) 224 + rw_ds_1_2_params 225 + 226 + let rw_handshake_no_data hs _ = 227 + let buf = Writer.assemble_handshake hs in 228 + match Reader.parse_handshake buf with 229 + | Ok hs' -> 230 + assert_equal hs hs' ; 231 + (* lets get crazy and do it one more time *) 232 + let buf' = Writer.assemble_handshake hs' in 233 + (match Reader.parse_handshake buf' with 234 + | Ok hs'' -> assert_equal hs hs'' 235 + | Error _ -> assert_failure "handshake no data inner failed") 236 + | Error _ -> assert_failure "handshake no data failed" 237 + 238 + let rw_handshakes_no_data_vals = [ Core.HelloRequest ; Core.ServerHelloDone ] 239 + 240 + let rw_handshake_no_data_tests = 241 + List.mapi 242 + (fun i f -> "handshake no data " ^ string_of_int i >:: rw_handshake_no_data f) 243 + rw_handshakes_no_data_vals 244 + 245 + let rw_handshake_cstruct_data hs _ = 246 + let buf = Writer.assemble_handshake hs in 247 + match Reader.parse_handshake buf with 248 + | Ok hs' -> 249 + Readertests.cmp_handshake_cstruct hs hs' ; 250 + (* lets get crazy and do it one more time *) 251 + let buf' = Writer.assemble_handshake hs' in 252 + (match Reader.parse_handshake buf' with 253 + | Ok hs'' -> Readertests.cmp_handshake_cstruct hs hs'' 254 + | Error _ -> assert_failure "handshake cstruct data inner failed") 255 + | Error _ -> assert_failure "handshake cstruct data failed" 256 + 257 + let rw_handshake_cstruct_data_vals = 258 + let data_cs = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11 ] in 259 + let emp = list_to_cstruct [ ] in 260 + Core.([ ServerKeyExchange emp ; 261 + ServerKeyExchange data_cs ; 262 + Finished emp ; 263 + Finished data_cs ; 264 + ClientKeyExchange emp ; 265 + ClientKeyExchange data_cs ; 266 + Certificate (Writer.assemble_certificates []) ; 267 + Certificate (Writer.assemble_certificates [data_cs]) ; 268 + Certificate (Writer.assemble_certificates [data_cs; data_cs]) ; 269 + Certificate (Writer.assemble_certificates [data_cs ; emp]) ; 270 + Certificate (Writer.assemble_certificates [emp ; data_cs]) ; 271 + Certificate (Writer.assemble_certificates [emp ; data_cs ; emp]) ; 272 + Certificate (Writer.assemble_certificates [emp ; data_cs ; emp ; data_cs]) 273 + ]) 274 + 275 + let rw_handshake_cstruct_data_tests = 276 + List.mapi 277 + (fun i f -> "handshake cstruct data " ^ string_of_int i >:: rw_handshake_cstruct_data f) 278 + rw_handshake_cstruct_data_vals 279 + 280 + let rw_handshake_client_hello hs _ = 281 + let buf = Writer.assemble_handshake hs in 282 + match Reader.parse_handshake buf with 283 + | Ok hs' -> 284 + Core.(match hs, hs' with 285 + | ClientHello ch, ClientHello ch' -> 286 + Readertests.cmp_client_hellos ch ch' ; 287 + | _ -> assert_failure "handshake client hello broken") ; 288 + (* lets get crazy and do it one more time *) 289 + let buf' = Writer.assemble_handshake hs' in 290 + (match Reader.parse_handshake buf' with 291 + | Ok hs'' -> 292 + Core.(match hs, hs'' with 293 + | ClientHello ch, ClientHello ch'' -> 294 + Readertests.cmp_client_hellos ch ch'' ; 295 + | _ -> assert_failure "handshake client hello broken") 296 + | Error _ -> assert_failure "handshake client hello inner failed") 297 + | Error _ -> assert_failure "handshake client hello failed" 298 + 299 + let rw_handshake_client_hello_vals = 300 + let rnd = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 301 + let client_random = list_to_cstruct (rnd @ rnd) in 302 + Core.(let ch : client_hello = 303 + { client_version = `TLS_1_2 ; 304 + client_random ; 305 + sessionid = None ; 306 + ciphersuites = [] ; 307 + extensions = []} 308 + in 309 + [ 310 + ClientHello ch ; 311 + ClientHello { ch with client_version = `TLS_1_0 } ; 312 + ClientHello { ch with client_version = `TLS_1_1 } ; 313 + 314 + ClientHello { ch with ciphersuites = [ Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA ] } ; 315 + ClientHello { ch with ciphersuites = Packet.([ TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_AES_256_CBC_SHA ]) } ; 316 + 317 + ClientHello { ch with sessionid = (Some (list_to_cstruct rnd)) } ; 318 + ClientHello { ch with sessionid = (Some client_random) } ; 319 + 320 + ClientHello { ch with 321 + ciphersuites = Packet.([ TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_AES_256_CBC_SHA ]) ; 322 + sessionid = (Some client_random) } ; 323 + 324 + ClientHello { ch with extensions = [ make_hostname_ext "foobar" ] } ; 325 + ClientHello { ch with extensions = [ make_hostname_ext "foobarblubb" ] } ; 326 + 327 + ClientHello { ch with extensions = [ make_hostname_ext "foobarblubb" ; `SupportedGroups Packet.([SECP521R1; SECP384R1]) ] } ; 328 + 329 + ClientHello { ch with extensions = [ `ALPN ["h2"; "http/1.1"] ] } ; 330 + 331 + ClientHello { ch with extensions = [ 332 + make_hostname_ext "foobarblubb" ; 333 + `SupportedGroups Packet.([SECP521R1; SECP384R1]) ; 334 + `SignatureAlgorithms [`RSA_PKCS1_MD5] ; 335 + `ALPN ["h2"; "http/1.1"] 336 + ] } ; 337 + 338 + ClientHello { ch with 339 + ciphersuites = Packet.([ TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_AES_256_CBC_SHA ]) ; 340 + sessionid = (Some client_random) ; 341 + extensions = [ make_hostname_ext "foobarblubb" ] } ; 342 + 343 + ClientHello { ch with 344 + ciphersuites = Packet.([ TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_AES_256_CBC_SHA ]) ; 345 + sessionid = (Some client_random) ; 346 + extensions = [ 347 + make_hostname_ext "foobarblubb" ; 348 + `SupportedGroups Packet.([SECP521R1; SECP384R1]) ; 349 + `SignatureAlgorithms [`RSA_PKCS1_SHA1; `RSA_PKCS1_SHA512] ; 350 + `ALPN ["h2"; "http/1.1"] 351 + ] } ; 352 + 353 + ClientHello { ch with 354 + ciphersuites = Packet.([ TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_AES_256_CBC_SHA ]) ; 355 + sessionid = (Some client_random) ; 356 + extensions = [ 357 + make_hostname_ext "foobarblubb" ; 358 + `SupportedGroups Packet.([SECP521R1; SECP384R1]) ; 359 + `SignatureAlgorithms [`RSA_PKCS1_MD5; `RSA_PKCS1_SHA256] ; 360 + `SecureRenegotiation client_random ; 361 + `ALPN ["h2"; "http/1.1"] 362 + ] } ; 363 + 364 + ]) 365 + 366 + let rw_handshake_client_hello_tests = 367 + List.mapi 368 + (fun i f -> "handshake client hello " ^ string_of_int i >:: rw_handshake_client_hello f) 369 + rw_handshake_client_hello_vals 370 + 371 + let rw_handshake_server_hello hs _ = 372 + let buf = Writer.assemble_handshake hs in 373 + (match Reader.parse_handshake buf with 374 + | Ok hs' -> 375 + Core.(match hs, hs' with 376 + | ServerHello sh, ServerHello sh' -> 377 + Readertests.cmp_server_hellos sh sh' ; 378 + | _ -> assert_failure "handshake server hello broken") ; 379 + (* lets get crazy and do it one more time *) 380 + let buf' = Writer.assemble_handshake hs' in 381 + (match Reader.parse_handshake buf' with 382 + | Ok hs'' -> 383 + Core.(match hs, hs'' with 384 + | ServerHello sh, ServerHello sh'' -> 385 + Readertests.cmp_server_hellos sh sh'' ; 386 + | _ -> assert_failure "handshake server hello broken") 387 + | Error _ -> assert_failure "handshake server hello inner failed") 388 + | Error _ -> assert_failure "handshake server hello failed") 389 + 390 + let rw_handshake_server_hello_vals = 391 + let rnd = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 392 + let server_random = list_to_cstruct (rnd @ rnd) in 393 + Core.(let sh : server_hello = 394 + { server_version = `TLS_1_2 ; 395 + server_random ; 396 + sessionid = None ; 397 + ciphersuite = `RSA_WITH_AES_256_CCM ; 398 + extensions = []} 399 + in 400 + [ 401 + ServerHello sh ; 402 + ServerHello { sh with server_version = `TLS_1_0 } ; 403 + ServerHello { sh with server_version = `TLS_1_1 } ; 404 + 405 + ServerHello { sh with sessionid = (Some server_random) } ; 406 + 407 + ServerHello { sh with 408 + sessionid = (Some server_random) ; 409 + extensions = [`Hostname] 410 + } ; 411 + 412 + ServerHello { sh with 413 + sessionid = (Some server_random) ; 414 + extensions = [`Hostname ; `SecureRenegotiation server_random] 415 + } ; 416 + 417 + ServerHello { sh with 418 + sessionid = (Some server_random) ; 419 + extensions = [`Hostname ; `SecureRenegotiation server_random ; `ALPN "h2"] 420 + } ; 421 + 422 + ]) 423 + 424 + let rw_handshake_server_hello_tests = 425 + List.mapi 426 + (fun i f -> "handshake server hello " ^ string_of_int i >:: rw_handshake_server_hello f) 427 + rw_handshake_server_hello_vals 428 + 429 + let readerwriter_tests = 430 + version_tests @ 431 + header_tests @ 432 + rw_alert_tests @ 433 + rw_dh_tests @ 434 + rw_ds_tests @ 435 + rw_ds_1_2_tests @ 436 + rw_handshake_no_data_tests @ 437 + rw_handshake_cstruct_data_tests @ 438 + rw_handshake_client_hello_tests @ 439 + rw_handshake_server_hello_tests
+1
vendor/opam/tls/tests/server.key
··· 1 + ../certificates/server.key
+1
vendor/opam/tls/tests/server.pem
··· 1 + ../certificates/server.pem
+65
vendor/opam/tls/tests/testlib.ml
··· 1 + open OUnit2 2 + 3 + let () = Mirage_crypto_rng_unix.use_default () 4 + 5 + let time f = 6 + let t1 = Sys.time () in 7 + let r = f () in 8 + let t2 = Sys.time () in 9 + ( Printf.eprintf "[time] %f.04 s\n%!" (t2 -. t1) ; r ) 10 + 11 + let list_to_cstruct xs = 12 + let buf = Bytes.create (List.length xs) in 13 + List.iteri (Bytes.set_uint8 buf) xs ; 14 + Bytes.unsafe_to_string buf 15 + 16 + let uint16_to_cstruct i = 17 + let buf = Bytes.create 2 in 18 + Bytes.set_uint16_be buf 0 i; 19 + buf 20 + 21 + let hexdump_to_str cs = 22 + Ohex.encode cs 23 + 24 + let assert_cs_eq ?msg cs1 cs2 = 25 + assert_equal 26 + ~cmp:String.equal 27 + ~printer:hexdump_to_str 28 + ?msg 29 + cs1 cs2 30 + 31 + let rec assert_lists_eq comparison a b = 32 + match a, b with 33 + | [], [] -> () 34 + | a::r1, b::r2 -> comparison a b ; assert_lists_eq comparison r1 r2 35 + | _ -> assert_failure "lists not equal" 36 + 37 + 38 + let assert_sessionid_equal a b = 39 + match a, b with 40 + | None, None -> () 41 + | Some x, Some y -> assert_cs_eq x y 42 + | _ -> assert_failure "session id not equal" 43 + 44 + let assert_client_extension_equal a b = 45 + match a, b with 46 + | `Hostname a, `Hostname b -> assert_equal a b 47 + | `MaxFragmentLength a, `MaxFragmentLength b -> assert_equal a b 48 + | `SupportedGroups a, `SupportedGroups b -> assert_lists_eq assert_equal a b 49 + | `SecureRenegotiation a, `SecureRenegotiation b -> assert_cs_eq a b 50 + | `Padding a, `Padding b -> assert_equal a b 51 + | `SignatureAlgorithms a, `SignatureAlgorithms b -> 52 + assert_lists_eq (fun sa sa' -> assert_equal sa sa') a b 53 + | `ALPN a, `ALPN b -> assert_lists_eq assert_equal a b 54 + | _ -> assert_failure "extensions did not match" 55 + 56 + let assert_server_extension_equal a b = 57 + match a, b with 58 + | `Hostname, `Hostname -> () 59 + | `MaxFragmentLength a, `MaxFragmentLength b -> assert_equal a b 60 + | `SecureRenegotiation a, `SecureRenegotiation b -> assert_cs_eq a b 61 + | `ALPN a, `ALPN b -> assert_equal a b 62 + | _ -> assert_failure "extensions did not match" 63 + 64 + let make_hostname_ext h = 65 + (`Hostname (Domain_name.of_string_exn h |> Domain_name.host_exn))
+3
vendor/opam/tls/tests/unittestrunner.ml
··· 1 + open OUnit2 2 + 3 + let () = run_test_tt_main Unittests.suite
+8
vendor/opam/tls/tests/unittests.ml
··· 1 + open OUnit2 2 + 3 + let suite = 4 + "All" >::: [ 5 + "Reader" >::: Readertests.reader_tests ; 6 + "Writer" >::: Writertests.writer_tests ; 7 + "ReaderWriter" >::: Readerwritertests.readerwriter_tests ; 8 + ]
+441
vendor/opam/tls/tests/writertests.ml
··· 1 + open OUnit2 2 + open Tls 3 + open Testlib 4 + 5 + let version_assembler (ver, res) _ = 6 + let buf = Writer.assemble_protocol_version ver in 7 + assert_cs_eq buf res 8 + 9 + let version_assembler_tests = [ 10 + (`TLS_1_0, list_to_cstruct [3; 1]) ; 11 + (`TLS_1_1, list_to_cstruct [3; 2]) ; 12 + (`TLS_1_2, list_to_cstruct [3; 3]) ; 13 + ] 14 + 15 + let version_tests = 16 + List.mapi 17 + (fun i f -> "Assemble version " ^ string_of_int i >:: version_assembler f) 18 + version_assembler_tests 19 + 20 + let hdr_assembler (ver, ct, cs, res) _ = 21 + let buf = Writer.assemble_hdr ver (ct, (list_to_cstruct cs)) in 22 + let res' = list_to_cstruct res in 23 + assert_cs_eq buf res' 24 + 25 + let hdr_assembler_tests = [ 26 + (`TLS_1_2, Packet.CHANGE_CIPHER_SPEC, [], [20; 3; 3; 0; 0]) ; 27 + (`TLS_1_1, Packet.CHANGE_CIPHER_SPEC, [], [20; 3; 2; 0; 0]) ; 28 + (`TLS_1_0, Packet.CHANGE_CIPHER_SPEC, [], [20; 3; 1; 0; 0]) ; 29 + (`TLS_1_2, Packet.CHANGE_CIPHER_SPEC, [0; 0; 0], [20; 3; 3; 0; 3; 0; 0; 0]) ; 30 + 31 + (`TLS_1_2, Packet.ALERT, [], [21; 3; 3; 0; 0]) ; 32 + (`TLS_1_1, Packet.ALERT, [], [21; 3; 2; 0; 0]) ; 33 + (`TLS_1_0, Packet.ALERT, [], [21; 3; 1; 0; 0]) ; 34 + (`TLS_1_2, Packet.ALERT, [0; 0; 0], [21; 3; 3; 0; 3; 0; 0; 0]) ; 35 + 36 + (`TLS_1_2, Packet.HANDSHAKE, [], [22; 3; 3; 0; 0]) ; 37 + (`TLS_1_1, Packet.HANDSHAKE, [], [22; 3; 2; 0; 0]) ; 38 + (`TLS_1_0, Packet.HANDSHAKE, [], [22; 3; 1; 0; 0]) ; 39 + (`TLS_1_2, Packet.HANDSHAKE, [0; 0; 0], [22; 3; 3; 0; 3; 0; 0; 0]) ; 40 + 41 + (`TLS_1_2, Packet.APPLICATION_DATA, [], [23; 3; 3; 0; 0]) ; 42 + (`TLS_1_1, Packet.APPLICATION_DATA, [], [23; 3; 2; 0; 0]) ; 43 + (`TLS_1_0, Packet.APPLICATION_DATA, [], [23; 3; 1; 0; 0]) ; 44 + (`TLS_1_2, Packet.APPLICATION_DATA, [0; 0; 0], [23; 3; 3; 0; 3; 0; 0; 0]) ; 45 + ] 46 + 47 + let hdr_tests = 48 + List.mapi 49 + (fun i f -> "Assemble header " ^ string_of_int i >:: hdr_assembler f) 50 + hdr_assembler_tests 51 + 52 + let alert_assembler (level, t, res) _ = 53 + let buf = match level with 54 + | None -> Writer.assemble_alert t 55 + | Some l -> Writer.assemble_alert ~level:l t 56 + in 57 + let res' = list_to_cstruct res in 58 + assert_cs_eq buf res' 59 + 60 + let alert_assembler_tests = Packet.([ 61 + ( None, CLOSE_NOTIFY , [ 2 ; 0; ] ) ; 62 + ( None, UNEXPECTED_MESSAGE , [ 2 ; 10; ] ) ; 63 + ( None, BAD_RECORD_MAC , [ 2 ; 20; ] ) ; 64 + ( None, RECORD_OVERFLOW , [ 2 ; 22; ] ) ; 65 + ( None, HANDSHAKE_FAILURE , [ 2 ; 40; ] ) ; 66 + ( None, BAD_CERTIFICATE , [ 2 ; 42; ] ) ; 67 + ( None, CERTIFICATE_EXPIRED , [ 2 ; 45; ] ) ; 68 + ( None, DECODE_ERROR , [ 2 ; 50; ] ) ; 69 + ( None, PROTOCOL_VERSION , [ 2 ; 70; ] ) ; 70 + ( None, USER_CANCELED , [ 2 ; 90; ] ) ; 71 + ( None, NO_RENEGOTIATION , [ 2 ; 100; ] ) ; 72 + ( None, UNSUPPORTED_EXTENSION , [ 2 ; 110; ] ) ; 73 + ( None, UNRECOGNIZED_NAME , [ 2 ; 112; ] ) ; 74 + ( None, NO_APPLICATION_PROTOCOL , [ 2 ; 120; ] ) ; 75 + 76 + ( Some FATAL, CLOSE_NOTIFY , [ 2 ; 0; ] ) ; 77 + ( Some FATAL, UNEXPECTED_MESSAGE , [ 2 ; 10; ] ) ; 78 + ( Some FATAL, BAD_RECORD_MAC , [ 2 ; 20; ] ) ; 79 + ( Some FATAL, RECORD_OVERFLOW , [ 2 ; 22; ] ) ; 80 + ( Some FATAL, HANDSHAKE_FAILURE , [ 2 ; 40; ] ) ; 81 + ( Some FATAL, BAD_CERTIFICATE , [ 2 ; 42; ] ) ; 82 + ( Some FATAL, CERTIFICATE_EXPIRED , [ 2 ; 45; ] ) ; 83 + ( Some FATAL, DECODE_ERROR , [ 2 ; 50; ] ) ; 84 + ( Some FATAL, PROTOCOL_VERSION , [ 2 ; 70; ] ) ; 85 + ( Some FATAL, USER_CANCELED , [ 2 ; 90; ] ) ; 86 + ( Some FATAL, NO_RENEGOTIATION , [ 2 ; 100; ] ) ; 87 + ( Some FATAL, UNSUPPORTED_EXTENSION , [ 2 ; 110; ] ) ; 88 + ( Some FATAL, UNRECOGNIZED_NAME , [ 2 ; 112; ] ) ; 89 + ( Some FATAL, NO_APPLICATION_PROTOCOL , [ 2 ; 120; ] ) ; 90 + 91 + ( Some WARNING, CLOSE_NOTIFY , [ 1 ; 0; ] ) ; 92 + ( Some WARNING, UNEXPECTED_MESSAGE , [ 1 ; 10; ] ) ; 93 + ( Some WARNING, BAD_RECORD_MAC , [ 1 ; 20; ] ) ; 94 + ( Some WARNING, RECORD_OVERFLOW , [ 1 ; 22; ] ) ; 95 + ( Some WARNING, HANDSHAKE_FAILURE , [ 1 ; 40; ] ) ; 96 + ( Some WARNING, BAD_CERTIFICATE , [ 1 ; 42; ] ) ; 97 + ( Some WARNING, CERTIFICATE_EXPIRED , [ 1 ; 45; ] ) ; 98 + ( Some WARNING, DECODE_ERROR , [ 1 ; 50; ] ) ; 99 + ( Some WARNING, PROTOCOL_VERSION , [ 1 ; 70; ] ) ; 100 + ( Some WARNING, USER_CANCELED , [ 1 ; 90; ] ) ; 101 + ( Some WARNING, NO_RENEGOTIATION , [ 1 ; 100; ] ) ; 102 + ( Some WARNING, UNSUPPORTED_EXTENSION , [ 1 ; 110; ] ) ; 103 + ( Some WARNING, UNRECOGNIZED_NAME , [ 1 ; 112; ] ) ; 104 + ]) 105 + 106 + let alert_tests = 107 + List.mapi 108 + (fun i f -> "Assemble alert " ^ string_of_int i >:: alert_assembler f) 109 + alert_assembler_tests 110 + 111 + let ccs_test _ = 112 + let buf = Writer.assemble_change_cipher_spec in 113 + assert_cs_eq buf (list_to_cstruct [1]) 114 + 115 + let dh_assembler (p, res) _ = 116 + let buf = Writer.assemble_dh_parameters p in 117 + assert_cs_eq buf res 118 + 119 + let dh_assembler_tests = 120 + let a = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 121 + let le = list_to_cstruct [ 0; 16 ] in 122 + let le2 = list_to_cstruct [ 0; 32 ] in 123 + let emp, empl = (list_to_cstruct [], list_to_cstruct [ 0; 0 ]) in 124 + Core.([ 125 + ( { dh_p = a ; dh_g = a ; dh_Ys = a }, 126 + le ^ a ^ le ^ a ^ le ^ a ) ; 127 + ( { dh_p = a ^ a ; dh_g = a ; dh_Ys = a ^ a }, 128 + le2 ^ a ^ a ^ le ^ a ^ le2 ^ a ^ a ) ; 129 + ( { dh_p = emp ; dh_g = emp ; dh_Ys = emp }, empl ^ empl ^ empl ) ; 130 + ( { dh_p = a ; dh_g = emp ; dh_Ys = emp }, le ^ a ^ empl ^ empl ) ; 131 + ( { dh_p = emp ; dh_g = a ; dh_Ys = emp }, empl ^ le ^ a ^ empl ) ; 132 + ( { dh_p = emp ; dh_g = emp ; dh_Ys = a }, empl ^ empl ^ le ^ a ) ; 133 + ( { dh_p = emp ; dh_g = a ; dh_Ys = a }, empl ^ le ^ a ^ le ^ a ) ; 134 + ( { dh_p = a ; dh_g = a ; dh_Ys = emp }, le ^ a ^ le ^ a ^ empl ) ; 135 + ( { dh_p = a ; dh_g = emp ; dh_Ys = a }, le ^ a ^ empl ^ le ^ a ) ; 136 + ]) 137 + 138 + let dh_tests = 139 + List.mapi 140 + (fun i f -> "Assemble dh parameters " ^ string_of_int i >:: dh_assembler f) 141 + dh_assembler_tests 142 + 143 + 144 + let ds_assembler (p, res) _ = 145 + let buf = Writer.assemble_digitally_signed p in 146 + assert_cs_eq buf res 147 + 148 + let ds_assembler_tests = 149 + let a = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 150 + let le = list_to_cstruct [ 0; 16 ] in 151 + let le2 = list_to_cstruct [ 0; 32 ] in 152 + let emp, empl = (list_to_cstruct [], list_to_cstruct [ 0; 0 ]) in 153 + [ 154 + ( a , le ^ a ) ; 155 + ( a ^ a , le2 ^ a ^ a ) ; 156 + ( emp , empl ) 157 + ] 158 + 159 + let ds_tests = 160 + List.mapi 161 + (fun i f -> "Assemble digitally signed " ^ string_of_int i >:: ds_assembler f) 162 + ds_assembler_tests 163 + 164 + let ds_1_2_assembler (sigalg, p, res) _ = 165 + let buf = Writer.assemble_digitally_signed_1_2 sigalg p in 166 + assert_cs_eq buf res 167 + 168 + let ds_1_2_assembler_tests = 169 + let a = list_to_cstruct [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 170 + let le = list_to_cstruct [ 0; 16 ] in 171 + let le2 = list_to_cstruct [ 0; 32 ] in 172 + let emp, empl = (list_to_cstruct [], list_to_cstruct [0; 0]) in 173 + [ 174 + ( `RSA_PKCS1_MD5, a , list_to_cstruct [1; 1] ^ le ^ a ) ; 175 + ( `RSA_PKCS1_SHA1, a ^ a , list_to_cstruct [2; 1] ^ le2 ^ a ^ a ) ; 176 + ( `RSA_PSS_RSAENC_SHA256, emp , list_to_cstruct [8; 4] ^ empl ) 177 + ] 178 + 179 + let ds_1_2_tests = 180 + List.mapi 181 + (fun i f -> "Assemble digitally signed 1.2 " ^ string_of_int i >:: ds_1_2_assembler f) 182 + ds_1_2_assembler_tests 183 + 184 + let handshake_assembler (h, res) _ = 185 + let res' = list_to_cstruct res in 186 + let buf = Writer.assemble_handshake h in 187 + assert_cs_eq buf res' 188 + 189 + let handshake_assembler_tests = 190 + let a_l = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15 ] in 191 + let a_cs = list_to_cstruct a_l in 192 + let le = [ 0; 0; 16 ] in 193 + let le2 = [ 0; 0; 32 ] in 194 + let emp, empl = (list_to_cstruct [], [ 0; 0; 0 ]) in 195 + Core.([ 196 + ( HelloRequest , [ 0; 0; 0; 0 ]) ; 197 + ( ServerHelloDone , [ 14; 0; 0; 0 ]) ; 198 + 199 + ( Finished a_cs , [ 20 ] @ le @ a_l ) ; 200 + ( Finished emp , [ 20 ] @ empl ) ; 201 + ( Finished (a_cs ^ a_cs) , [ 20 ] @ le2 @ a_l @ a_l ) ; 202 + 203 + ( ClientKeyExchange emp , [ 16; 0; 0; 0 ] ) ; 204 + ( ClientKeyExchange a_cs , [ 16; 0; 0; 16 ] @ a_l ) ; 205 + ( ClientKeyExchange (a_cs ^ a_cs) , [ 16; 0; 0; 32 ] @ a_l @ a_l ) ; 206 + 207 + ( ServerKeyExchange emp , [ 12 ] @ empl ) ; 208 + ( ServerKeyExchange a_cs , [ 12 ] @ le @ a_l ) ; 209 + ( ServerKeyExchange (a_cs ^ a_cs) , [ 12 ] @ le2 @ a_l @ a_l ) ; 210 + 211 + ( Certificate (Writer.assemble_certificates []) , [ 11; 0; 0; 3; 0; 0; 0 ] ) ; 212 + ( Certificate (Writer.assemble_certificates[emp]) , [ 11; 0; 0; 6; 0; 0; 3; 0; 0; 0 ] ) ; 213 + ( Certificate (Writer.assemble_certificates[emp ; emp]) , [ 11; 0; 0; 9; 0; 0; 6; 0; 0; 0; 0; 0; 0 ] ) ; 214 + 215 + ( Certificate (Writer.assemble_certificates[a_cs]) , [ 11; 0; 0; 22; 0; 0; 19 ] @ le @ a_l ) ; 216 + ( Certificate (Writer.assemble_certificates[a_cs ; emp]) , [ 11; 0; 0; 25; 0; 0; 22 ] @ le @ a_l @ [ 0; 0; 0 ] ) ; 217 + ( Certificate (Writer.assemble_certificates[emp ; a_cs]) , [ 11; 0; 0; 25; 0; 0; 22; 0; 0; 0] @ le @ a_l ) ; 218 + ( Certificate (Writer.assemble_certificates[emp ; a_cs ; emp]) , [ 11; 0; 0; 28; 0; 0; 25; 0; 0; 0 ] @ le @ a_l @ [ 0; 0; 0 ]) ; 219 + ( Certificate (Writer.assemble_certificates[a_cs ; emp ; a_cs]) , [ 11; 0; 0; 44; 0; 0; 41 ] @ le @ a_l @ [ 0; 0; 0 ] @ le @ a_l ) ; 220 + ( Certificate (Writer.assemble_certificates[a_cs ; emp ; a_cs ; emp]) , [ 11; 0; 0; 47; 0; 0; 44 ] @ le @ a_l @ [ 0; 0; 0 ] @ le @ a_l @ [ 0; 0; 0 ] ) ; 221 + 222 + ( ClientHello { client_version = `TLS_1_2 ; 223 + client_random = a_cs ^ a_cs ; 224 + sessionid = None ; 225 + ciphersuites = [] ; 226 + extensions = [] }, 227 + [ 1; 0; 0; 39; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 0; 1; 0 ] ) ; 228 + 229 + ( ClientHello { client_version = `TLS_1_1 ; 230 + client_random = a_cs ^ a_cs ; 231 + sessionid = None ; 232 + ciphersuites = [] ; 233 + extensions = [] }, 234 + [ 1; 0; 0; 39; 3; 2 ] @ a_l @ a_l @ [ 0; 0; 0; 1; 0 ] ) ; 235 + 236 + ( ClientHello { client_version = `TLS_1_0 ; 237 + client_random = a_cs ^ a_cs ; 238 + sessionid = None ; 239 + ciphersuites = [] ; 240 + extensions = [] }, 241 + [ 1; 0; 0; 39; 3; 1 ] @ a_l @ a_l @ [ 0; 0; 0; 1; 0 ] ) ; 242 + 243 + ( ClientHello { client_version = `TLS_1_2 ; 244 + client_random = a_cs ^ a_cs ; 245 + sessionid = None ; 246 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] ; 247 + extensions = [] }, 248 + [ 1; 0; 0; 41; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 2; 0; 0x0a; 1; 0 ] ) ; 249 + 250 + ( ClientHello { client_version = `TLS_1_2 ; 251 + client_random = a_cs ^ a_cs ; 252 + sessionid = None ; 253 + ciphersuites = Packet.([TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_AES_128_CBC_SHA ; TLS_DHE_RSA_WITH_AES_128_CBC_SHA]); 254 + extensions = [] }, 255 + [ 1; 0; 0; 47; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 8; 0; 0x0A; 0; 0x16; 0; 0x2F; 0; 0x33; 1; 0 ] ) ; 256 + 257 + 258 + ( ClientHello { client_version = `TLS_1_2 ; 259 + client_random = a_cs ^ a_cs ; 260 + sessionid = None ; 261 + ciphersuites = Packet.([TLS_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA ; TLS_RSA_WITH_AES_128_CBC_SHA ; TLS_DHE_RSA_WITH_AES_128_CBC_SHA]); 262 + extensions = [ 263 + `SignatureAlgorithms 264 + [`RSA_PKCS1_SHA512 ; 265 + `RSA_PKCS1_SHA384 ; 266 + `RSA_PKCS1_SHA256 ; 267 + `RSA_PKCS1_SHA224 ; 268 + `RSA_PKCS1_SHA1 ] ] }, 269 + [ 1; 0; 0; 65; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 8; 0; 0x0A; 0; 0x16; 0; 0x2F; 0; 0x33; 1; 0 ; 0; 0x10 ; 270 + 271 + 0x00; 0x0d; 0x00; 0x0c; (* signature algorithms *) 272 + 0x00; 0x0a; 0x06; 0x01; 0x05; 0x01; 0x04; 0x01; 0x03; 0x01; 0x02; 0x01 ] ) ; 273 + 274 + 275 + ( ClientHello { client_version = `TLS_1_2 ; 276 + client_random = a_cs ^ a_cs ; 277 + sessionid = None ; 278 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] ; 279 + extensions = [`ALPN ["h2"; "http/1.1"]] }, 280 + [ 1; 0; 0; 61; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 2; 0; 0x0A; 1; 0; 0; 18; 0; 16; 0; 14; 0; 12; 2; 104; 50; 8; 104; 116; 116; 112; 47; 49; 46; 49 ] ) ; 281 + 282 + 283 + ( ClientHello { client_version = `TLS_1_2 ; 284 + client_random = a_cs ^ a_cs ; 285 + sessionid = None ; 286 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] ; 287 + extensions = [make_hostname_ext "foo"] }, 288 + [ 1; 0; 0; 55; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 2; 0; 0x0A; 1; 0; 0; 12; 0; 0; 0; 8; 0; 6; 0; 0; 3; 102; 111; 111 ] ) ; 289 + 290 + ( ClientHello { client_version = `TLS_1_2 ; 291 + client_random = a_cs ^ a_cs ; 292 + sessionid = None ; 293 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] ; 294 + extensions = [make_hostname_ext "foofoofoofoofoofoofoofoofoofoo"] }, 295 + [ 1; 0; 0; 82; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 2; 0; 0x0A; 1; 0; 0; 39; 0; 0; 0; 35; 0; 33; 0; 0; 30; 102; 111; 111; 102; 111; 111; 102; 111; 111; 102; 111; 111; 102; 111; 111; 102; 111; 111; 102; 111; 111; 102; 111; 111; 102; 111; 111; 102; 111; 111 ] ) ; 296 + 297 + ( ClientHello { client_version = `TLS_1_2 ; 298 + client_random = a_cs ^ a_cs ; 299 + sessionid = None ; 300 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] ; 301 + extensions = [make_hostname_ext "foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof"] }, 302 + [ 1; 0; 0; 232; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 2; 0; 0x0A; 1; 0; 0; 189; 0; 0; 0; 185; 0; 183; 0; 0; 180; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102 ] ) ; 303 + 304 + (* this one is the smallest which needs extra padding 305 + (due to its size being > 256 and < 511) *) 306 + ( ClientHello { client_version = `TLS_1_2 ; 307 + client_random = a_cs ^ a_cs ; 308 + sessionid = None ; 309 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] ; 310 + extensions = [make_hostname_ext "foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoofoofo"] }, 311 + [ 1; 0; 1; 0xFC; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 2; 0; 0x0A; 1; 0; 1; 0xD1; 0; 0; 0; 0xD0; 0; 0xCE; 0; 0; 0xCB; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111; 0; 21; 0; 0xF9; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0 ] ) ; 312 + 313 + (* this one is the biggest which needs no extra padding *) 314 + ( ClientHello { client_version = `TLS_1_2 ; 315 + client_random = a_cs ^ a_cs ; 316 + sessionid = None ; 317 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA] ; 318 + extensions = [make_hostname_ext "foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo.foofoofoofoofoof"] }, 319 + [ 1; 0; 0; 251; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 2; 0; 0x0A; 1; 0; 0; 208; 0; 0; 0; 204; 0; 202; 0; 0; 199; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 46; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102;111;111; 102 ] ) ; 320 + 321 + (* this one is the biggest which needs no extra padding, and no exts *) 322 + ( ClientHello { client_version = `TLS_1_2 ; 323 + client_random = a_cs ^ a_cs ; 324 + sessionid = None ; 325 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; 326 + Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; 327 + Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; 328 + Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA ] ; 329 + extensions = [] }, 330 + [ 1; 0; 0; 251; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 212; 0; 0x0A; 331 + 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 332 + 1; 0 ] ) ; 333 + 334 + (* add one more, and we get into padding no exts *) 335 + ( ClientHello { client_version = `TLS_1_2 ; 336 + client_random = a_cs ^ a_cs ; 337 + sessionid = None ; 338 + ciphersuites = [Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; 339 + Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; 340 + Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA; 341 + Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA;Packet.TLS_RSA_WITH_3DES_EDE_CBC_SHA ] ; 342 + extensions = [] }, 343 + [ 1; 0; 1; 0xFC; 3; 3 ] @ a_l @ a_l @ [ 0; 0; 214; 0; 0x0A; 0; 0x0A; 344 + 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 0;0x0A;0;0x0A;0;0x0A;0;0x0A;0;0x0A; 345 + 1; 0; 346 + 0;0xFD;0;0x15;0;0xF9; 347 + 0;0;0;0;0;0;0;0;0; 348 + 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0; 349 + ] ) ; 350 + 351 + ( ServerHello { server_version = `TLS_1_2 ; 352 + server_random = a_cs ^ a_cs ; 353 + sessionid = None ; 354 + ciphersuite = `RSA_WITH_AES_128_CCM ; 355 + extensions = [] 356 + } , 357 + [2; 0; 0; 38; 3; 3] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] ) ; 358 + 359 + ( ServerHello { server_version = `TLS_1_1 ; 360 + server_random = a_cs ^ a_cs ; 361 + sessionid = None ; 362 + ciphersuite = `RSA_WITH_AES_128_CCM ; 363 + extensions = [] 364 + } , 365 + [2; 0; 0; 38; 3; 2] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] ) ; 366 + 367 + ( ServerHello { server_version = `TLS_1_0 ; 368 + server_random = a_cs ^ a_cs ; 369 + sessionid = None ; 370 + ciphersuite = `RSA_WITH_AES_128_CCM ; 371 + extensions = [] 372 + } , 373 + [2; 0; 0; 38; 3; 1] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] ) ; 374 + 375 + 376 + ( ServerHello { server_version = `TLS_1_0 ; 377 + server_random = a_cs ^ a_cs ; 378 + sessionid = Some a_cs ; 379 + ciphersuite = `RSA_WITH_AES_128_CCM ; 380 + extensions = [] 381 + } , 382 + [2; 0; 0; 54; 3; 1] @ a_l @ a_l @ (* session id *) [ 16 ] @ a_l @ [(* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *)] ) ; 383 + 384 + ( ServerHello { server_version = `TLS_1_2 ; 385 + server_random = a_cs ^ a_cs ; 386 + sessionid = None ; 387 + ciphersuite = `RSA_WITH_AES_128_CCM ; 388 + extensions = [`Hostname] 389 + } , 390 + [2; 0; 0; 44; 3; 3] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 4; 0; 0; 0; 0] ) ; 391 + 392 + 393 + ( ServerHello { server_version = `TLS_1_2 ; 394 + server_random = a_cs ^ a_cs ; 395 + sessionid = None ; 396 + ciphersuite = `RSA_WITH_AES_128_CCM ; 397 + extensions = [`SecureRenegotiation ("")] 398 + } , 399 + [2; 0; 0; 45; 3; 3] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 5; 0xFF; 1; 0; 1; 0] ) ; 400 + 401 + ( ServerHello { server_version = `TLS_1_2 ; 402 + server_random = a_cs ^ a_cs ; 403 + sessionid = None ; 404 + ciphersuite = `RSA_WITH_AES_128_CCM ; 405 + extensions = [`Hostname ; `SecureRenegotiation ("")] 406 + } , 407 + [2; 0; 0; 49; 3; 3] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 9; 0; 0; 0; 0; 0xFF; 1; 0; 1; 0] ) ; 408 + 409 + ( ServerHello { server_version = `TLS_1_2 ; 410 + server_random = a_cs ^ a_cs ; 411 + sessionid = None ; 412 + ciphersuite = `RSA_WITH_AES_128_CCM ; 413 + extensions = [`SecureRenegotiation (""); `Hostname ] 414 + } , 415 + [2; 0; 0; 49; 3; 3] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 9; 0xFF; 1; 0; 1; 0; 0; 0; 0; 0] ) ; 416 + 417 + ( ServerHello { server_version = `TLS_1_2 ; 418 + server_random = a_cs ^ a_cs ; 419 + sessionid = None ; 420 + ciphersuite = `RSA_WITH_AES_128_CCM ; 421 + extensions = [`ALPN "h2"] 422 + } , 423 + [2; 0; 0; 49; 3; 3] @ a_l @ a_l @ [(* session id *) 0; (* cipher *) 0xc0; 0x9c; (* comp *) 0; (* exts *) 0; 9; 0; 16; 0; 5; 0; 3; 2; 104; 50] ) ; 424 + 425 + (* | CertificateRequest of certificate_request *) 426 + ]) 427 + 428 + let handshake_tests = 429 + List.mapi 430 + (fun i f -> "Assemble handshake " ^ string_of_int i >:: handshake_assembler f) 431 + handshake_assembler_tests 432 + 433 + let writer_tests = 434 + version_tests @ 435 + hdr_tests @ 436 + alert_tests @ 437 + ["CCS " >:: ccs_test] @ 438 + dh_tests @ 439 + ds_tests @ 440 + ds_1_2_tests @ 441 + handshake_tests
+34
vendor/opam/tls/tls-async.opam
··· 1 + opam-version: "2.0" 2 + homepage: "https://github.com/mirleft/ocaml-tls" 3 + dev-repo: "git+https://github.com/mirleft/ocaml-tls.git" 4 + bug-reports: "https://github.com/mirleft/ocaml-tls/issues" 5 + doc: "https://mirleft.github.io/ocaml-tls/doc" 6 + author: ["David Kaloper <david@numm.org>" "Hannes Mehnert <hannes@mehnert.org>" "Eric Ebinger <github@eric.theebingers.com>" "Calascibetta Romain <romain.calascibetta@gmail.com>"] 7 + maintainer: ["Hannes Mehnert <hannes@mehnert.org>" "David Kaloper <david@numm.org>"] 8 + license: "BSD-2-Clause" 9 + 10 + build: [ 11 + ["dune" "subst"] {dev} 12 + ["dune" "build" "-p" name "-j" jobs] 13 + ["dune" "runtest" "-p" name "-j" jobs] {with-test} 14 + ] 15 + 16 + depends: [ 17 + "ocaml" {>= "4.14.0"} 18 + "dune" {>= "3.0"} 19 + "tls" {= version} 20 + "ptime" {>= "0.8.1"} 21 + "async" {>= "v0.16"} 22 + "async_unix" {>= "v0.16"} 23 + "core" {>= "v0.16"} 24 + "core_unix" {>= "v0.16"} 25 + "cstruct-async" 26 + "ppx_jane" {>= "v0.16"} 27 + "mirage-crypto-rng" {>= "1.2.0"} 28 + ] 29 + tags: [ "org:mirage"] 30 + synopsis: "Transport Layer Security purely in OCaml, Async layer" 31 + description: """ 32 + Tls-async provides Async-friendly tls bindings 33 + """ 34 + x-maintenance-intent: [ "(latest)" ]
+45
vendor/opam/tls/tls-eio.opam
··· 1 + opam-version: "2.0" 2 + homepage: "https://github.com/mirleft/ocaml-tls" 3 + dev-repo: "git+https://github.com/mirleft/ocaml-tls.git" 4 + bug-reports: "https://github.com/mirleft/ocaml-tls/issues" 5 + doc: "https://mirleft.github.io/ocaml-tls/doc" 6 + authors: ["Thomas Leonard"] 7 + maintainer: ["Hannes Mehnert <hannes@mehnert.org>" "David Kaloper <david@numm.org>"] 8 + license: "BSD-2-Clause" 9 + 10 + build: [ 11 + ["dune" "subst"] {dev} 12 + ["dune" "build" "-p" name "-j" jobs] 13 + ["dune" "runtest" "-p" name "-j" jobs] {with-test & os != "macos"} 14 + ] 15 + 16 + depends: [ 17 + "ocaml" {>= "5.0.0"} 18 + "dune" {>= "3.0"} 19 + "tls" {= version} 20 + "mirage-crypto-rng" {>= "1.2.0"} 21 + "eio" {>= "0.12"} 22 + "eio_main" {>= "0.12" & with-test} 23 + "mdx" {with-test} 24 + "crowbar" {>= "0.2.1" & with-test} 25 + "logs" {>= "0.7.0" & with-test} 26 + "ptime" {>= "1.0.0"} 27 + ] 28 + tags: [ "org:mirage"] 29 + synopsis: "Transport Layer Security purely in OCaml - Eio" 30 + description: """ 31 + Transport Layer Security (TLS) is probably the most widely deployed security 32 + protocol on the Internet. It provides communication privacy to prevent 33 + eavesdropping, tampering, and message forgery. Furthermore, it optionally 34 + provides authentication of the involved endpoints. TLS is commonly deployed for 35 + securing web services ([HTTPS](http://tools.ietf.org/html/rfc2818)), emails, 36 + virtual private networks, and wireless networks. 37 + 38 + TLS uses asymmetric cryptography to exchange a symmetric key, and optionally 39 + authenticate (using X.509) either or both endpoints. It provides algorithmic 40 + agility, which means that the key exchange method, symmetric encryption 41 + algorithm, and hash algorithm are negotiated. 42 + 43 + Read our [Usenix Security 2015 paper](https://www.usenix.org/conference/usenixsecurity15/technical-sessions/presentation/kaloper-mersinjak). 44 + """ 45 + x-maintenance-intent: [ "(latest)" ]
+32
vendor/opam/tls/tls-lwt.opam
··· 1 + opam-version: "2.0" 2 + homepage: "https://github.com/mirleft/ocaml-tls" 3 + dev-repo: "git+https://github.com/mirleft/ocaml-tls.git" 4 + bug-reports: "https://github.com/mirleft/ocaml-tls/issues" 5 + doc: "https://mirleft.github.io/ocaml-tls/doc" 6 + author: ["David Kaloper <david@numm.org>" "Hannes Mehnert <hannes@mehnert.org>"] 7 + maintainer: ["Hannes Mehnert <hannes@mehnert.org>" "David Kaloper <david@numm.org>"] 8 + license: "BSD-2-Clause" 9 + 10 + build: [ 11 + ["dune" "subst"] {dev} 12 + ["dune" "build" "-p" name "-j" jobs] 13 + ["dune" "runtest" "-p" name "-j" jobs] {with-test} 14 + ] 15 + 16 + depends: [ 17 + "ocaml" {>= "4.13.0"} 18 + "dune" {>= "3.0"} 19 + "tls" {= version} 20 + "mirage-crypto-rng" {>= "1.2.0"} 21 + "lwt" {>= "5.7.0"} 22 + "cmdliner" {>= "1.1.0"} 23 + "ptime" {>= "0.8.1"} 24 + "randomconv" {with-test & >= "0.2.0"} 25 + ] 26 + conflicts: [ "result" {< "1.5"} ] 27 + tags: [ "org:mirage"] 28 + synopsis: "Transport Layer Security purely in OCaml, Lwt layer" 29 + description: """ 30 + Tls-lwt provides an effectful Tls_lwt module to be used with Lwt. 31 + """ 32 + x-maintenance-intent: [ "(latest)" ]
+34
vendor/opam/tls/tls-miou-unix.opam
··· 1 + opam-version: "2.0" 2 + homepage: "https://github.com/mirleft/ocaml-tls" 3 + dev-repo: "git+https://github.com/mirleft/ocaml-tls.git" 4 + bug-reports: "https://github.com/mirleft/ocaml-tls/issues" 5 + doc: "https://mirleft.github.io/ocaml-tls/" 6 + author: ["Romain Calascibetta <romain.calascibetta@gmail.com>"] 7 + maintainer: ["Romain Calascibetta <romain.calascibetta@gmail.com>"] 8 + license: "BSD-2-Clause" 9 + 10 + build: [ 11 + ["dune" "subst"] {dev} 12 + ["dune" "build" "-p" name "-j" jobs] 13 + ["dune" "runtest" "-p" name "-j" jobs] {with-test} 14 + ] 15 + 16 + depends: [ 17 + "ocaml" {>= "5.0.0"} 18 + "dune" {>= "3.0"} 19 + "tls" {= version} 20 + "mirage-crypto-rng-miou-unix" {>= "1.0.0" & with-test} 21 + "x509" {>= "1.0.0"} 22 + "miou" {>= "0.3.0"} 23 + "crowbar" {with-test} 24 + "rresult" {with-test} 25 + "ohex" {with-test} 26 + "ptime" {with-test} 27 + "hxd" {with-test} 28 + ] 29 + tags: [ "org:mirage"] 30 + synopsis: "Transport Layer Security purely in OCaml, Miou+Unix layer" 31 + description: """ 32 + Tls-miou provides an effectful Tls_miou module to be used with Miou and Unix. 33 + """ 34 + x-maintenance-intent: [ "(latest)" ]
+35
vendor/opam/tls/tls-mirage.opam
··· 1 + opam-version: "2.0" 2 + homepage: "https://github.com/mirleft/ocaml-tls" 3 + dev-repo: "git+https://github.com/mirleft/ocaml-tls.git" 4 + bug-reports: "https://github.com/mirleft/ocaml-tls/issues" 5 + doc: "https://mirleft.github.io/ocaml-tls/doc" 6 + author: ["David Kaloper <david@numm.org>" "Hannes Mehnert <hannes@mehnert.org>"] 7 + maintainer: ["Hannes Mehnert <hannes@mehnert.org>" "David Kaloper <david@numm.org>"] 8 + license: "BSD-2-Clause" 9 + 10 + build: [ 11 + ["dune" "subst"] {dev} 12 + ["dune" "build" "-p" name "-j" jobs] 13 + ["dune" "runtest" "-p" name "-j" jobs] {with-test} 14 + ] 15 + 16 + depends: [ 17 + "ocaml" {>= "4.13.0"} 18 + "dune" {>= "3.0"} 19 + "tls" {= version} 20 + "fmt" {>= "0.8.7"} 21 + "lwt" {>= "3.0.0"} 22 + "mirage-flow" {>= "4.0.0"} 23 + "mirage-kv" {>= "3.0.0"} 24 + "mirage-ptime" {>= "4.0.0"} 25 + "ptime" {>= "0.8.1"} 26 + "mirage-crypto" {>= "1.0.0"} 27 + "mirage-crypto-pk" {>= "1.0.0"} 28 + ] 29 + tags: [ "org:mirage"] 30 + synopsis: "Transport Layer Security purely in OCaml, MirageOS layer" 31 + description: """ 32 + Tls-mirage provides an effectful FLOW module to be used in the MirageOS 33 + ecosystem. 34 + """ 35 + x-maintenance-intent: [ "(latest)" ]
+55
vendor/opam/tls/tls.opam
··· 1 + opam-version: "2.0" 2 + homepage: "https://github.com/mirleft/ocaml-tls" 3 + dev-repo: "git+https://github.com/mirleft/ocaml-tls.git" 4 + bug-reports: "https://github.com/mirleft/ocaml-tls/issues" 5 + doc: "https://mirleft.github.io/ocaml-tls/doc" 6 + author: ["David Kaloper <david@numm.org>" "Hannes Mehnert <hannes@mehnert.org>"] 7 + maintainer: ["Hannes Mehnert <hannes@mehnert.org>" "David Kaloper <david@numm.org>"] 8 + license: "BSD-2-Clause" 9 + 10 + build: [ 11 + ["dune" "subst"] {dev} 12 + ["dune" "build" "-p" name "-j" jobs] 13 + ["dune" "runtest" "-p" name "-j" jobs] {with-test} 14 + ] 15 + 16 + depends: [ 17 + "ocaml" {>= "4.13.0"} 18 + "dune" {>= "3.0"} 19 + "mirage-crypto" {>= "1.1.0"} 20 + "mirage-crypto-ec" {>= "1.0.0"} 21 + "mirage-crypto-pk" {>= "1.0.0"} 22 + "mirage-crypto-rng" {>= "1.2.0"} 23 + "x509" {>= "1.0.0"} 24 + "domain-name" {>= "0.3.0"} 25 + "fmt" {>= "0.8.7"} 26 + "ounit2" {with-test & >= "2.2.0"} 27 + "kdf" {>= "1.0.0"} 28 + "logs" 29 + "ipaddr" 30 + "ohex" {>= "0.2.0"} 31 + "digestif" {>= "1.2.0"} 32 + "ptime" {>= "1.2.0"} 33 + "alcotest" {with-test} 34 + "cmdliner" {with-test & >= "1.3.0"} 35 + ] 36 + conflicts: [ "result" {< "1.5"} ] 37 + tags: [ "org:mirage"] 38 + synopsis: "Transport Layer Security purely in OCaml" 39 + description: """ 40 + Transport Layer Security (TLS) is probably the most widely deployed security 41 + protocol on the Internet. It provides communication privacy to prevent 42 + eavesdropping, tampering, and message forgery. Furthermore, it optionally 43 + provides authentication of the involved endpoints. TLS is commonly deployed for 44 + securing web services ([HTTPS](http://tools.ietf.org/html/rfc2818)), emails, 45 + virtual private networks, and wireless networks. 46 + 47 + TLS uses asymmetric cryptography to exchange a symmetric key, and optionally 48 + authenticate (using X.509) either or both endpoints. It provides algorithmic 49 + agility, which means that the key exchange method, symmetric encryption 50 + algorithm, and hash algorithm are negotiated. 51 + 52 + Read our [Usenix Security 2015 paper](https://www.usenix.org/conference/usenixsecurity15/technical-sessions/presentation/kaloper-mersinjak). 53 + """ 54 + available: [ arch != "arm32" ] # see SIGBUS failures at https://github.com/ocaml/opam-repository/pull/26387 55 + x-maintenance-intent: [ "(latest)" ]
+5
vendor/opam/tls/unix/dune
··· 1 + (library 2 + (name tls_unix) 3 + (public_name tls.unix) 4 + (wrapped false) 5 + (libraries tls unix ptime.clock.os mirage-crypto-rng.unix))
+339
vendor/opam/tls/unix/tls_unix.ml
··· 1 + (* NOTE: mostly copied from miou/tls_miou_unix.ml, so any change should be synchronized. *) 2 + 3 + let src = Logs.Src.create "tls-unix" 4 + 5 + module Log = (val Logs.src_log src : Logs.LOG) 6 + 7 + external reraise : exn -> 'a = "%reraise" 8 + 9 + let ( $ ) f x = f x 10 + 11 + exception Tls_alert of Tls.Packet.alert_type 12 + exception Tls_failure of Tls.Engine.failure 13 + exception Closed_by_peer 14 + 15 + let () = 16 + Printexc.register_printer @@ function 17 + | Closed_by_peer -> Some "Connection closed by peer" 18 + | Tls_alert alert -> Some (Tls.Packet.alert_type_to_string alert) 19 + | Tls_failure failure -> Some (Tls.Engine.string_of_failure failure) 20 + | _ -> None 21 + 22 + type state = 23 + [ `Active of Tls.Engine.state 24 + | `Read_closed of Tls.Engine.state 25 + | `Write_closed of Tls.Engine.state 26 + | `Closed 27 + | `Error of exn ] 28 + 29 + type t = { 30 + role : [ `Server | `Client ]; 31 + fd : Unix.file_descr; 32 + mutable state : state; 33 + mutable linger : string option; 34 + read_buffer_size : int; 35 + buf : bytes; 36 + mutable rd_closed : bool; 37 + } 38 + 39 + let file_descr { fd; _ } = fd 40 + 41 + let half_close state mode = 42 + match (state, mode) with 43 + | `Active tls, `read -> `Read_closed tls 44 + | `Active tls, `write -> `Write_closed tls 45 + | `Active _, `read_write -> `Closed 46 + | `Read_closed tls, `read -> `Read_closed tls 47 + | `Read_closed _, (`write | `read_write) -> `Closed 48 + | `Write_closed tls, `write -> `Write_closed tls 49 + | `Write_closed _, (`read | `read_write) -> `Closed 50 + | ((`Closed | `Error _) as e), (`read | `write | `read_write) -> e 51 + 52 + let inject_state tls = function 53 + | `Active _ -> `Active tls 54 + | `Read_closed _ -> `Read_closed tls 55 + | `Write_closed _ -> `Write_closed tls 56 + | (`Closed | `Error _) as e -> e 57 + 58 + let tls_alert a = Tls_alert a 59 + let tls_fail f = Tls_failure f 60 + let inhibit fn v = try fn v with _ -> () 61 + 62 + let rec unix_write fd str off len = 63 + let written = Unix.write_substring fd str off len in 64 + if not (Int.equal written len) then 65 + unix_write fd str (off + written) (len - written) 66 + 67 + let write flow str = 68 + Log.debug (fun m -> m "try to write %d byte(s)" (String.length str)); 69 + try unix_write flow.fd str 0 (String.length str) with 70 + | Unix.Unix_error ((Unix.EPIPE | Unix.ECONNRESET), _, _) -> 71 + flow.state <- half_close flow.state `write; 72 + raise Closed_by_peer 73 + | Unix.Unix_error (_, _, _) as exn -> 74 + flow.state <- `Error exn; 75 + reraise exn 76 + 77 + let handle flow tls str = 78 + match Tls.Engine.handle_tls tls str with 79 + | Ok (state, eof, `Response resp, `Data data) -> 80 + Log.debug (fun m -> m "We handled %d byte(s)" (String.length str)); 81 + let state = inject_state state flow.state in 82 + let state = Option.(value ~default:state (map (fun `Eof -> half_close state `read) eof)) in 83 + flow.state <- state; 84 + let to_close = flow.state = `Closed in 85 + Option.iter (inhibit $ write flow) resp; 86 + (* NOTE(dinosaure): [write flow] can set [flow.state]. So we must 87 + check if the actual [flow.state] or the [flow.state] after [write flow] 88 + want to close the underlying file-descriptor. *) 89 + if to_close || flow.state = `Closed then Unix.close flow.fd; 90 + data 91 + | Error (fail, `Response resp) -> 92 + let exn = match fail with 93 + | `Alert a -> tls_alert a | f -> tls_fail f in 94 + flow.state <- `Error exn; 95 + let _ = inhibit (write flow) resp in 96 + raise exn 97 + 98 + let read flow = 99 + match Unix.read flow.fd flow.buf 0 (Bytes.length flow.buf) with 100 + | 0 -> Ok String.empty 101 + | len -> Ok (Bytes.sub_string flow.buf 0 len) 102 + | exception Unix.Unix_error (Unix.ECONNRESET, _, _) -> Ok String.empty 103 + | exception exn -> Error exn 104 + 105 + let not_errored = function `Error _ -> false | _ -> true 106 + 107 + let garbage flow = match flow.linger with 108 + | Some "" | None -> false 109 + | _ -> true 110 + 111 + let read_react flow = 112 + match flow.state with 113 + | `Error exn -> raise exn 114 + | `Read_closed _ | `Closed when garbage flow -> 115 + (* XXX(dinosaure): [`Closed] can appear "at the same time" than some 116 + application-data. In that case, we stored them into [t.linger]. Depending 117 + on who closed the connection, [read_react] gives this /garbage/ in any 118 + situation (even if the user closed the connection). 119 + 120 + An extra layer with [read] below check if [`Read_closed]/[`Close] comes 121 + from the network (the peer closed the connection) or the user. In the 122 + first case, we must give pending application-data. In the second case, 123 + we must return [0] (or raise [End_of_file]). *) 124 + let mbuf = flow.linger in 125 + flow.linger <- None; 126 + mbuf 127 + | `Read_closed _ | `Closed -> 128 + (* XXX(dinosaure): the goal of [read_react] is to read some encrypted bytes 129 + and try to decrypt them with [handle]. If the linger is empty, this means 130 + that we're trying to get more data (to decrypt) when we can't get any 131 + more. From this point of view, it's an error that needs to be notified. 132 + However, this error can be interpreted in 2 ways: 133 + - we want to have more data decrypted. In this case, this error is 134 + expected and may result in the user being told that there is nothing 135 + left to read (for example, returning 0). 136 + - we attempt a handshake. In this case, we are dealing with an unexpected 137 + error. *) 138 + raise End_of_file 139 + | `Active _ | `Write_closed _ -> 140 + Log.debug (fun m -> m "read something from the TLS session"); 141 + match read flow with 142 + | Error exn -> 143 + if not_errored flow.state then flow.state <- `Error exn; 144 + raise exn 145 + | Ok "" -> 146 + (* XXX(dinosaure): see [`Read_closed _ | `Closed] case. *) 147 + raise End_of_file 148 + | Ok str -> 149 + Log.debug (fun m -> m "got %d byte(s)" (String.length str)); 150 + match flow.state with 151 + | `Active tls | `Read_closed tls | `Write_closed tls -> handle flow tls str 152 + | `Closed -> raise End_of_file 153 + | `Error exn -> raise exn 154 + [@@ocamlformat "disable"] 155 + 156 + let rec read_in flow ?(off= 0) ?len buf = 157 + let len = Option.value ~default:(Bytes.length buf - off) len in 158 + let write_in res = 159 + let rlen = String.length res in 160 + let mlen = min len rlen in 161 + Bytes.blit_string res 0 buf off mlen; 162 + let linger = if mlen < rlen 163 + then Some (String.sub res mlen (rlen - mlen)) 164 + else None in 165 + flow.linger <- linger; mlen 166 + in 167 + match flow.linger with 168 + | Some res -> write_in res 169 + | None -> ( 170 + match read_react flow with 171 + | None -> read_in ~off ~len flow buf 172 + | Some res -> write_in res) 173 + 174 + let writev flow bufs = 175 + match flow.state with 176 + | `Closed | `Write_closed _ -> raise Closed_by_peer 177 + | `Error exn -> reraise exn 178 + | `Active tls | `Read_closed tls -> ( 179 + match Tls.Engine.send_application_data tls bufs with 180 + | Some (tls, answer) -> 181 + flow.state <- inject_state tls flow.state; 182 + write flow answer 183 + | None -> assert false) 184 + 185 + let rec drain_handshake flow = 186 + let push_linger flow mcs = 187 + match (mcs, flow.linger) with 188 + | None, _ -> () 189 + | scs, None -> flow.linger <- scs 190 + | Some cs, Some l -> flow.linger <- Some (l ^ cs) 191 + in 192 + match flow.state with 193 + | `Active tls when not (Tls.Engine.handshake_in_progress tls) -> flow 194 + | (`Read_closed _ | `Closed) when garbage flow -> flow 195 + | _ -> 196 + Log.debug (fun m -> m "start to read something from the TLS session"); 197 + let mcs = read_react flow in 198 + push_linger flow mcs; 199 + drain_handshake flow 200 + 201 + let close flow = 202 + match flow.state with 203 + | `Active tls | `Read_closed tls -> 204 + let tls, str = Tls.Engine.send_close_notify tls in 205 + flow.rd_closed <- true; 206 + flow.state <- inject_state tls flow.state; 207 + flow.state <- `Closed; 208 + inhibit (write flow) str; 209 + Unix.close flow.fd 210 + | `Write_closed _ -> 211 + flow.rd_closed <- true; 212 + flow.state <- `Closed; 213 + Unix.close flow.fd 214 + | `Closed -> flow.rd_closed <- true 215 + | `Error _ -> 216 + flow.rd_closed <- true; 217 + Unix.close flow.fd 218 + 219 + let closed_by_user flow = function 220 + | `read | `read_write -> flow.rd_closed <- true 221 + | `write -> () 222 + 223 + let shutdown flow mode = 224 + closed_by_user flow mode; 225 + match (flow.state, mode) with 226 + | `Active tls, `read -> 227 + Log.debug (fun m -> m "shutdown `read"); 228 + flow.state <- inject_state tls (half_close flow.state mode) 229 + | (`Active tls | `Read_closed tls), (`write | `read_write) -> 230 + let tls, str = Tls.Engine.send_close_notify tls in 231 + flow.state <- inject_state tls (half_close flow.state mode); 232 + (* NOTE(dinosaure): [write flow] can set [flow.state]. So we must 233 + check if the actual [flow.state] or the [flow.state] after [write flow] 234 + want to close the underlying file-descriptor. *) 235 + let to_close = flow.state = `Closed in 236 + inhibit (write flow) str; 237 + if to_close || flow.state = `Closed then Unix.close flow.fd 238 + | `Write_closed tls, (`read | `read_write) -> 239 + flow.state <- inject_state tls (half_close flow.state mode); 240 + if flow.state = `Closed then Unix.close flow.fd 241 + | `Error _, _ -> Unix.close flow.fd 242 + | `Read_closed _, `read -> () 243 + | `Write_closed _, `write -> () 244 + | `Closed, _ -> () 245 + 246 + let client_of_fd conf ?(read_buffer_size = 0x1000) ?host fd = 247 + let conf' = 248 + match host with None -> conf | Some host -> Tls.Config.peer conf host 249 + in 250 + let tls, init = Tls.Engine.client conf' in 251 + let tls_flow = 252 + { 253 + role = `Client; 254 + fd; 255 + state = `Active tls; 256 + linger = None; 257 + read_buffer_size; 258 + buf = Bytes.make read_buffer_size '\000'; 259 + rd_closed = false; 260 + } 261 + in 262 + write tls_flow init; 263 + drain_handshake tls_flow 264 + 265 + let server_of_fd conf ?(read_buffer_size = 0x1000) fd = 266 + let tls = Tls.Engine.server conf in 267 + let tls_flow = 268 + { 269 + role = `Server; 270 + fd; 271 + state = `Active tls; 272 + linger = None; 273 + read_buffer_size; 274 + buf = Bytes.make read_buffer_size '\000'; 275 + rd_closed = false; 276 + } 277 + in 278 + drain_handshake tls_flow 279 + 280 + let write flow ?(off = 0) ?len str = 281 + let len = Option.value ~default:(String.length str - off) len in 282 + if off < 0 || len < 0 || off > String.length str - len 283 + then invalid_arg "Tls_unix.write"; 284 + if len > 0 then writev flow [ String.sub str off len ] 285 + 286 + let read t ?(off= 0) ?len buf = 287 + let len = Option.value ~default:(Bytes.length buf - off) len in 288 + if off < 0 || len < 0 || off > Bytes.length buf - len 289 + then invalid_arg "Tls_unix.read"; 290 + if t.rd_closed then 0 291 + else try read_in t ~off ~len buf with End_of_file -> 0 292 + 293 + let rec really_read_go t off len buf = 294 + let len' = read t buf ~off ~len in 295 + if len' == 0 then raise End_of_file 296 + else if len - len' > 0 297 + then really_read_go t (off + len') (len - len') buf 298 + 299 + let really_read t ?(off= 0) ?len buf = 300 + let len = Option.value ~default:(Bytes.length buf - off) len in 301 + if off < 0 || len < 0 || off > Bytes.length buf - len 302 + then invalid_arg "Tls_unix.really_read"; 303 + if len > 0 then really_read_go t off len buf 304 + 305 + let resolve host service = 306 + let tcp = Unix.getprotobyname "tcp" in 307 + match Unix.getaddrinfo host service [ AI_PROTOCOL tcp.p_proto ] with 308 + | [] -> Fmt.invalid_arg "No address for %s:%s" host service 309 + | ai :: _ -> ai.ai_addr 310 + 311 + let connect authenticator (v, port) = 312 + let conf = 313 + match Tls.Config.client ~authenticator () with 314 + | Ok config -> config 315 + | Error `Msg msg -> Fmt.invalid_arg "Configuration failure: %s" msg 316 + in 317 + let addr = resolve v (string_of_int port) in 318 + let fd = 319 + match addr with 320 + | Unix.ADDR_UNIX _ -> invalid_arg "Tls_unix.connect: Invalid UNIX socket" 321 + | Unix.ADDR_INET (inet_addr, _) -> 322 + if Unix.is_inet6_addr inet_addr then 323 + Unix.socket Unix.PF_INET6 Unix.SOCK_STREAM 0 324 + else 325 + Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 326 + in 327 + let host = Result.to_option Domain_name.(Result.bind (of_string v) host) in 328 + match Unix.connect fd addr with 329 + | () -> client_of_fd conf ?host fd 330 + | exception exn -> 331 + Unix.close fd; 332 + raise exn 333 + 334 + let epoch flow = match flow.state with 335 + | `Active tls | `Read_closed tls | `Write_closed tls -> 336 + ( match Tls.Engine.epoch tls with 337 + | Error () -> assert false 338 + | Ok data -> Some data ) 339 + | _ -> None
+96
vendor/opam/tls/unix/tls_unix.mli
··· 1 + (** Effectful operations using Unix for pure TLS. 2 + 3 + The pure TLS is state and buffer in, state and buffer out. This module uses 4 + the Unix layer for communication over the network. *) 5 + 6 + exception Tls_alert of Tls.Packet.alert_type 7 + exception Tls_failure of Tls.Engine.failure 8 + exception Closed_by_peer 9 + 10 + type t 11 + (** Abstract type of a session. *) 12 + 13 + val file_descr : t -> Unix.file_descr 14 + (** [file_descr] returns the underlying file-descriptor used by the given 15 + TLS {i socket}. *) 16 + 17 + val read : t -> ?off:int -> ?len:int -> bytes -> int 18 + (** [read fd buf ~off ~len] reads up to [len] bytes (defaults to 19 + [Bytes.length buf - off] from the given TLS {i socket} [fd], storing them in 20 + byte sequence [buf], starting at position [off] in [buf] (defaults to [0]). 21 + It returns the actual number of characters read, between 0 and [len] 22 + (inclusive). 23 + 24 + @raise Unix_error raised by the system call {!val:Unix.read}. The function 25 + handles {!val:Unix.EINTR}, {!val:Unix.EAGAIN} and {!val:Unix.EWOULDBLOCK} 26 + exceptions and redo the system call. 27 + 28 + @raise Invalid_argument if [off] and [len] do not designate a valid range of 29 + [buf]. *) 30 + 31 + val really_read : t -> ?off:int -> ?len:int -> bytes -> unit 32 + (** [really_read fd buf ~off ~len] reads [len] bytes (defaults to 33 + [Bytes.length buf - off]) from the given TLS {i socket} [fd], storing them 34 + in byte sequence [buf], starting at position [off] in [buf] (defaults to 35 + [0]). If [len = 0], [really_read] does nothing. 36 + 37 + @raise Unix_error raised by the system call {!val:Unix.read}. The function 38 + handles {!val:Unix.EINTR}, {!val:Unix.EAGAIN} and {!val:Unix.EWOULDBLOCK} 39 + exceptions and redo the system call. 40 + 41 + @raise End_of_file if {!val:Unix.read} returns [0] before [len] characters 42 + have been read. 43 + 44 + @raise Invalid_argument if [off] and [len] do not designate a valid range of 45 + [buf]. *) 46 + 47 + val write : t -> ?off:int -> ?len:int -> string -> unit 48 + (** [write t str ~off ~len] writes [len] bytes (defaults to 49 + [String.length str - off]) from byte sequence [str], starting at offset 50 + [off] (defaults to [0]), to the given TLS {i socket} [fd]. 51 + 52 + @raise Unix_error raised by the syscall call {!val:Unix.write}. The function 53 + handles {!val:Unix.EINTR}, {!val:Unix.EAGAIN} and {!val:Unix.EWOULDBLOCK} 54 + exceptions and redo the system call. 55 + 56 + @raise Closed_by_peer if [t] is connected to a peer whose reading end is 57 + closed. Similar to the {!val:EPIPE} error for pipe/socket connected. 58 + 59 + @raise Invalid_argument if [off] and [len] do not designate a valid range of 60 + [buf]. *) 61 + 62 + val close : t -> unit 63 + (** [close flow] closes the TLS session and the underlying file-descriptor. *) 64 + 65 + val shutdown : t -> [ `read | `write | `read_write ] -> unit 66 + (** [shutdown t direction] closes the direction of the TLS session [t]. If 67 + [`read_write] or [`write] is closed, a TLS close-notify is sent to the other 68 + endpoint. If this results in a fully-closed session (or an errorneous 69 + session), the underlying file descriptor is closed. *) 70 + 71 + val client_of_fd : 72 + Tls.Config.client -> 73 + ?read_buffer_size:int -> 74 + ?host:[ `host ] Domain_name.t -> 75 + Unix.file_descr -> 76 + t 77 + (** [client_of_flow client ~host fd] is [t], after client-side TLS handshake of 78 + [fd] using [client] configuration and [host]. 79 + 80 + @raise End_of_file if we are not able to complete the handshake. *) 81 + 82 + val server_of_fd : 83 + Tls.Config.server -> ?read_buffer_size:int -> Unix.file_descr -> t 84 + (** [server_of_fd server fd] is [t], after server-side TLS handshake of [fd] 85 + using [server] configuration. 86 + 87 + @raise End_of_file if we are not able to complete the handshake. *) 88 + 89 + val connect : X509.Authenticator.t -> string * int -> t 90 + (** [connect authenticator (host, port)] is [t], a connected TLS connection 91 + to [host] on [port] using the default configuration and the 92 + [authenticator]. *) 93 + 94 + val epoch : t -> Tls.Core.epoch_data option 95 + (** [epoch t] returns [epoch], which contains information of the active 96 + session. *)