diff --git a/Cargo.lock b/Cargo.lock index 2c41da646..cefa56832 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,679 +4,678 @@ name = "aho-corasick" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.11", ] [[package]] name = "autocfg" -version = "0.1.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bindgen" version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003f95e0fb6cf3d1fee8c62b2ec35135509477989fab15c358e0efa3972bdef6" dependencies = [ - "cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clang-sys 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cexpr", + "clang-sys", + "docopt", + "env_logger", + "libc", + "log 0.3.9", + "rustc-serialize", + "syntex_syntax", ] [[package]] name = "bitflags" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" [[package]] name = "bitflags" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "block-cipher-trait" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array", ] [[package]] name = "block-modes" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait", + "block-padding", ] [[package]] name = "block-padding" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools", ] [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" -version = "1.3.2" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "cc" -version = "1.0.45" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d" [[package]] name = "cexpr" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" dependencies = [ - "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nom", ] [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chrono" -version = "0.4.9" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "num-integer", + "num-traits", + "time", + "winapi 0.3.9", ] [[package]] name = "clang-sys" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19911f7964ce61a02d382adee8400f919d0fedd53c5441e3d6a9858ba73e249e" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0", + "glob", + "libc", ] [[package]] name = "cmake" -version = "0.1.42" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "core_io" version = "0.1.20190701" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb3b45b225c233ea8b95309256e842264692c68eeb543e06755de9072dd1178a" dependencies = [ - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "docopt" version = "0.6.86" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a7ef30445607f6fc8720f0a0a2c7442284b629cf0d049286860fae23e71c4d9" dependencies = [ - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "regex", + "rustc-serialize", + "strsim", ] [[package]] name = "env_logger" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9", + "regex", ] [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" [[package]] name = "hex" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "lazy_static" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "libz-sys" -version = "1.0.25" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.11", ] [[package]] name = "log" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "mbedtls" version = "0.6.1" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", - "core_io 0.1.20190701 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mbedtls-sys-auto 2.18.5", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rc2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rs-libc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_cbor 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "yasna 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1", + "block-modes", + "byteorder", + "cc", + "chrono", + "core_io", + "hex", + "libc", + "matches", + "mbedtls-sys-auto", + "rand", + "rc2", + "rs-libc", + "serde", + "serde_cbor", + "serde_derive", + "spin", + "yasna", ] [[package]] name = "mbedtls-sys-auto" version = "2.18.5" dependencies = [ - "bindgen 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "bindgen", + "cmake", + "libc", + "libz-sys", ] [[package]] name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "nom" version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.2", ] [[package]] name = "num-integer" -version = "0.1.41" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "num-traits", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", ] [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "pkg-config" -version = "0.3.16" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "proc-macro2" -version = "0.4.30" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.1", ] [[package]] name = "quote" -version = "0.6.13" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "rand" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi 0.3.9", ] [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2", ] [[package]] name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] name = "rc2" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039209d71774c9b2ae967ffb66b73ed253b3c384c198ec0d620fdd5369c78e5e" dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait", + "opaque-debug", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex" version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr 0.1.11", + "regex-syntax", + "thread_local", + "utf8-ranges", ] [[package]] name = "regex-syntax" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" [[package]] name = "rs-libc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80a671d6c4696a49b78e0a271c99bc58bc1a17a64893a3684a1ba1a944b26ca9" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "rustc_version" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] [[package]] name = "semver" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" [[package]] name = "serde_bytes" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", ] [[package]] name = "serde_cbor" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27181cf088428830792d77a40dd44f59d663f3e909bd56cef8c815403cf814ba" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "serde", + "serde_bytes", ] [[package]] name = "serde_derive" -version = "1.0.70" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "spin" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" [[package]] name = "strsim" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" [[package]] name = "syn" -version = "0.14.9" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid 0.2.1", ] [[package]] name = "syntex_errors" version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290933a450229bbbeee92bc4900ed0300ba54b59a0741055284c709cf2938f03" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "log 0.3.9", + "rustc-serialize", + "syntex_pos", + "term", + "unicode-xid 0.0.3", ] [[package]] name = "syntex_pos" version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c37a0a6e73cc9d6c7a16fb955bc97fb8eb513b2d7ac23279adca58548a204ca" dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize", ] [[package]] name = "syntex_syntax" version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c64b3581fad872d6b28ccad01e0a0db0c4af70acd491af6650499a5fb35c9e8" dependencies = [ - "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.5.0", + "libc", + "log 0.3.9", + "rustc-serialize", + "syntex_errors", + "syntex_pos", + "term", + "unicode-xid 0.0.3", ] [[package]] name = "term" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "winapi 0.2.8", ] [[package]] name = "thread-id" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "libc", ] [[package]] name = "thread_local" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread-id", ] [[package]] name = "time" -version = "0.1.42" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "wasi", + "winapi 0.3.9", ] [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-xid" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" [[package]] name = "unicode-xid" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "utf8-ranges" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" [[package]] name = "vcpkg" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "yasna" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum bindgen 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "003f95e0fb6cf3d1fee8c62b2ec35135509477989fab15c358e0efa3972bdef6" -"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" -"checksum block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" -"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" -"checksum clang-sys 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19911f7964ce61a02d382adee8400f919d0fedd53c5441e3d6a9858ba73e249e" -"checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" -"checksum core_io 0.1.20190701 (registry+https://github.com/rust-lang/crates.io-index)" = "bb3b45b225c233ea8b95309256e842264692c68eeb543e06755de9072dd1178a" -"checksum docopt 0.6.86 (registry+https://github.com/rust-lang/crates.io-index)" = "4a7ef30445607f6fc8720f0a0a2c7442284b629cf0d049286860fae23e71c4d9" -"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" -"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rc2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "039209d71774c9b2ae967ffb66b73ed253b3c384c198ec0d620fdd5369c78e5e" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum rs-libc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80a671d6c4696a49b78e0a271c99bc58bc1a17a64893a3684a1ba1a944b26ca9" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_bytes 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "defbb8a83d7f34cc8380751eeb892b825944222888aff18996ea7901f24aec88" -"checksum serde_cbor 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27181cf088428830792d77a40dd44f59d663f3e909bd56cef8c815403cf814ba" -"checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" -"checksum spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ceac490aa12c567115b40b7b7fceca03a6c9d53d5defea066123debc83c5dc1f" -"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syntex_errors 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)" = "290933a450229bbbeee92bc4900ed0300ba54b59a0741055284c709cf2938f03" -"checksum syntex_pos 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c37a0a6e73cc9d6c7a16fb955bc97fb8eb513b2d7ac23279adca58548a204ca" -"checksum syntex_syntax 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c64b3581fad872d6b28ccad01e0a0db0c4af70acd491af6650499a5fb35c9e8" -"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum yasna 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "79af3189e6b0484c9fd54208f8eeb8818cadee00ec81438b67a64c8e6f2f3694" +checksum = "79af3189e6b0484c9fd54208f8eeb8818cadee00ec81438b67a64c8e6f2f3694" diff --git a/mbedtls-sys/Cargo.toml b/mbedtls-sys/Cargo.toml index f0dd423c8..e926bcb02 100644 --- a/mbedtls-sys/Cargo.toml +++ b/mbedtls-sys/Cargo.toml @@ -12,6 +12,7 @@ This version generates the correct bindings at compile time using bindgen.""" readme = "../README.md" repository = "https://github.com/fortanix/rust-mbedtls" documentation = "https://docs.rs/mbedtls-sys-auto/" +links = "mbedtls_sys" [lib] name = "mbedtls_sys" diff --git a/mbedtls-sys/build/cmake.rs b/mbedtls-sys/build/cmake.rs index 673ed3903..d2c7fc4b6 100644 --- a/mbedtls-sys/build/cmake.rs +++ b/mbedtls-sys/build/cmake.rs @@ -49,5 +49,7 @@ impl super::BuildConfig { println!("cargo:rustc-link-lib=mbedtls"); println!("cargo:rustc-link-lib=mbedx509"); println!("cargo:rustc-link-lib=mbedcrypto"); + + println!("cargo:include={}/{}", ::std::env::current_dir().unwrap().display(), self.mbedtls_src.join("include").display()); } } diff --git a/mbedtls/Cargo.toml b/mbedtls/Cargo.toml index f9605a243..393b4b954 100644 --- a/mbedtls/Cargo.toml +++ b/mbedtls/Cargo.toml @@ -38,8 +38,10 @@ default-features = false features = ["custom_printf", "trusted_cert_callback"] path = "../mbedtls-sys" + + [dev-dependencies] -libc = "0.2.0" +libc = "0.2.69" rand = "0.4.0" serde_cbor = "0.6" hex = "0.3" diff --git a/mbedtls/build.rs b/mbedtls/build.rs index 004c8a9c1..18dce7f22 100644 --- a/mbedtls/build.rs +++ b/mbedtls/build.rs @@ -12,6 +12,8 @@ use std::env; fn main() { let mut b = cc::Build::new(); + b.include(env::var_os("DEP_MBEDTLS_SYS_INCLUDE").expect("Links was not properly set in mbedtls-sys package, missing DEP_MBEDTLS_SYS_INCLUDE")); + b.file("src/rust_malloc.c"); b.file("src/rust_printf.c"); if env::var_os("CARGO_FEATURE_STD").is_none() || ::std::env::var("TARGET") @@ -22,9 +24,12 @@ fn main() { .define("_FORTIFY_SOURCE", Some("0")) .flag("-ffreestanding"); } + b.compile("librust-mbedtls.a"); + // Force correct link order for mbedtls_printf println!("cargo:rustc-link-lib=static=mbedtls"); println!("cargo:rustc-link-lib=static=mbedx509"); println!("cargo:rustc-link-lib=static=mbedcrypto"); + } diff --git a/mbedtls/examples/client.rs b/mbedtls/examples/client.rs index 8b405e3b4..69f1c548a 100644 --- a/mbedtls/examples/client.rs +++ b/mbedtls/examples/client.rs @@ -14,8 +14,9 @@ use std::net::TcpStream; use mbedtls::rng::CtrDrbg; use mbedtls::ssl::config::{Endpoint, Preset, Transport}; use mbedtls::ssl::{Config, Context}; -use mbedtls::x509::Certificate; +use mbedtls::x509::{MbedtlsList, Certificate}; use mbedtls::Result as TlsResult; +use std::sync::Arc; #[path = "../tests/support/mod.rs"] mod support; @@ -23,21 +24,21 @@ use support::entropy::entropy_new; use support::keys; fn result_main(addr: &str) -> TlsResult<()> { - let mut entropy = entropy_new(); - let mut rng = CtrDrbg::new(&mut entropy, None)?; - let mut cert = Certificate::from_pem(keys::PEM_CERT)?; + let entropy = Arc::new(entropy_new()); + let rng = Arc::new(CtrDrbg::new(entropy, None)?); + let cert = Arc::new(MbedtlsList::::from_pem(keys::PEM_CERT)?); let mut config = Config::new(Endpoint::Client, Transport::Stream, Preset::Default); - config.set_rng(Some(&mut rng)); - config.set_ca_list(Some(&mut *cert), None); - let mut ctx = Context::new(&config)?; + config.set_rng(rng); + config.set_ca_list(cert, None); + let mut ctx = Context::new(Arc::new(config)); - let mut conn = TcpStream::connect(addr).unwrap(); - let mut session = ctx.establish(&mut conn, None)?; + let conn = TcpStream::connect(addr).unwrap(); + ctx.establish(conn, None)?; let mut line = String::new(); stdin().read_line(&mut line).unwrap(); - session.write_all(line.as_bytes()).unwrap(); - io::copy(&mut session, &mut stdout()).unwrap(); + ctx.write_all(line.as_bytes()).unwrap(); + io::copy(&mut ctx, &mut stdout()).unwrap(); Ok(()) } diff --git a/mbedtls/examples/server.rs b/mbedtls/examples/server.rs index 59f8d7597..a0ba5eb12 100644 --- a/mbedtls/examples/server.rs +++ b/mbedtls/examples/server.rs @@ -15,8 +15,9 @@ use mbedtls::pk::Pk; use mbedtls::rng::CtrDrbg; use mbedtls::ssl::config::{Endpoint, Preset, Transport}; use mbedtls::ssl::{Config, Context}; -use mbedtls::x509::Certificate; +use mbedtls::x509::{MbedtlsList, Certificate}; use mbedtls::Result as TlsResult; +use std::sync::Arc; #[path = "../tests/support/mod.rs"] mod support; @@ -29,21 +30,25 @@ fn listen Result<(), E>>(mut handle_client: F) -> Resu println!("Connection from {}", conn.peer_addr().unwrap()); handle_client(conn)?; } + Ok(()) } fn result_main() -> TlsResult<()> { - let mut entropy = entropy_new(); - let mut rng = CtrDrbg::new(&mut entropy, None)?; - let mut cert = Certificate::from_pem(keys::PEM_CERT)?; - let mut key = Pk::from_private_key(keys::PEM_KEY, None)?; + let entropy = entropy_new(); + let rng = Arc::new(CtrDrbg::new(Arc::new(entropy), None)?); + let cert = Arc::new(MbedtlsList::::from_pem(keys::PEM_CERT)?); + let key = Arc::new(Pk::from_private_key(keys::PEM_KEY, None)?); let mut config = Config::new(Endpoint::Server, Transport::Stream, Preset::Default); - config.set_rng(Some(&mut rng)); - config.push_cert(&mut *cert, &mut key)?; - let mut ctx = Context::new(&config)?; + config.set_rng(rng); + config.push_cert(cert, key)?; + + let rc_config = Arc::new(config); - listen(|mut conn| { - let mut session = BufReader::new(ctx.establish(&mut conn, None)?); + listen(move |conn| { + let mut ctx = Context::new(rc_config.clone()); + ctx.establish(conn, None)?; + let mut session = BufReader::new(ctx); let mut line = Vec::new(); session.read_until(b'\n', &mut line).unwrap(); session.get_mut().write_all(&line).unwrap(); diff --git a/mbedtls/src/lib.rs b/mbedtls/src/lib.rs index a5e15df43..55c80e892 100644 --- a/mbedtls/src/lib.rs +++ b/mbedtls/src/lib.rs @@ -163,3 +163,15 @@ pub unsafe extern "C" fn mbedtls_time(tp: *mut time_t) -> time_t { } timestamp } + +// Debug not available in SGX +#[cfg(not(target_env = "sgx"))] +pub fn set_global_debug_threshold(threshold: i32) { + unsafe { mbedtls_sys::debug_set_threshold(threshold); } +} + + +extern "C" { + pub fn forward_mbedtls_calloc(n: mbedtls_sys::types::size_t, size: mbedtls_sys::types::size_t) -> *mut mbedtls_sys::types::raw_types::c_void; + pub fn forward_mbedtls_free(n: *mut mbedtls_sys::types::raw_types::c_void); +} diff --git a/mbedtls/src/pk/dhparam.rs b/mbedtls/src/pk/dhparam.rs index 6c785efb5..a5227232d 100644 --- a/mbedtls/src/pk/dhparam.rs +++ b/mbedtls/src/pk/dhparam.rs @@ -18,6 +18,12 @@ define!( impl<'a> Into {} ); +impl Into<*mut mbedtls_sys::dhm_context> for &Dhm { + fn into(self) -> *mut mbedtls_sys::dhm_context { + &self.inner as *const _ as *mut _ + } +} + impl Dhm { /// Takes both DER and PEM forms of FFDH parameters in `DHParams` format. /// diff --git a/mbedtls/src/pk/mod.rs b/mbedtls/src/pk/mod.rs index 48e643de8..bd544a0fb 100644 --- a/mbedtls/src/pk/mod.rs +++ b/mbedtls/src/pk/mod.rs @@ -132,6 +132,7 @@ const CUSTOM_PK_INFO: pk_info_t = { } }; +// If this changes then certificate.rs unsafe code in public_key needs to also change. define!( #[c_ty(pk_context)] #[repr(C)] @@ -142,6 +143,97 @@ define!( impl<'a> UnsafeFrom {} ); +impl Into<*mut mbedtls_sys::pk_context> for &Pk { + fn into(self) -> *mut mbedtls_sys::pk_context { + &self.inner as *const _ as *mut _ + } +} + +/// # Safety +/// +/// Thread safety analysis for Pk. +/// +/// A. Usage example of Pk. +/// +/// 1.1. Common use case is to to pass it as parameter to the SSL Config class. +/// 1.2. SSL Config class is then used by multiple Context classes (one for each connection) +/// 1.3. Context classes, handled by different threads will do calls towards Pk. +/// +/// Since this is a common use case for MbedTLS it should be thread safe if threading is enabled. +/// +/// B. Verifying thread safety. +/// +/// 1. Calls towards the specific Pk implementation are done via function pointers. +/// +/// - Example call towards Pk: +/// ../../../mbedtls-sys/vendor/library/ssl_srv.c:3707 - mbedtls_pk_decrypt( private_key, p, len, ... +/// - This calls a generic function pointer via: +/// ../../../mbedtls-sys/vendor/crypto/library/pk.c:475 - return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, +/// +/// 2. Pk implementation types. +/// +/// - The function pointers are defined via function: +/// ../../../mbedtls-sys/vendor/crypto/library/pk.c:115 - mbedtls_pk_info_from_type +/// - They are as follows: mbedtls_rsa_info / mbedtls_eckey_info / mbedtls_ecdsa_info +/// - These are defined in: +/// ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:196 +/// +/// C. Checking types one by one. +/// +/// 1. RSA: mbedtls_rsa_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:196 +/// This uses internal locks in: ../../../mbedtls-sys/vendor/crypto/library/rsa.c:718 +/// +/// 2. ECKEY: mbedtls_eckey_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:418 +/// This does not use internal locks but avoids interior mutability. +/// +/// Function checks one by one: +/// - Only const access to context: eckey_check_pair, eckey_get_bitlen, eckey_can_do, eckey_check_pair +/// +/// - Const acccess / copies context to a stack based variable +/// eckey_verify_wrap, eckey_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:251 +/// creates a stack ecdsa variable and uses ctx to initialize it. +/// ctx is passed as 'key', a const pointer to mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) +/// ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:819 +/// int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +/// key does not mutate. +/// +/// - Ignored due to not defined: eckey_verify_rs_wrap, eckey_sign_rs_wrap +/// (Undefined - MBEDTLS_ECP_RESTARTABLE - ../../../mbedtls-sys/build/config.rs:173) +/// +/// - Only used when creating/freeing - which is safe by design - eckey_alloc_wrap / eckey_free_wrap +/// +/// 3. ECDSA: mbedtls_ecdsa_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:729 +/// This does not use internal locks but avoids interior mutability. +/// +/// - Const access / copies context to stack based variables: +/// ecdsa_verify_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:544 +/// This copies the public key on the stack - in buf[] and copies the group id and nbits. +/// That is done via: mbedtls_pk_write_pubkey( &p, buf, &key ) where key.pk_ctx = ctx; +/// And the key is a const parameter to mbedtls_pk_write_pubkey - ../../../mbedtls-sys/vendor/crypto/library/pkwrite.c:158 +/// +/// - Const access with additional notes due to call stacks involved. +/// +/// ecdsa_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:657 +/// mbedtls_ecdsa_write_signature ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:688 +/// mbedtls_ecdsa_write_signature_restartable ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:640 +/// MBEDTLS_ECDSA_DETERMINISTIC is not defined. +/// MBEDTLS_ECDSA_SIGN_ALT is not defined. +/// Passes grp to: ecdsa_sign_restartable: ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:253 +/// Const access to group - reads parameters, passed as const to mbedtls_ecp_gen_privkey, +/// mbedtls_ecp_mul_restartable: ../../../mbedtls-sys/vendor/crypto/library/ecp.c:2351 +/// MBEDTLS_ECP_INTERNAL_ALT is not defined. (otherwise it might not be safe depending on ecp_init/ecp_free) ../../../mbedtls-sys/build/config.rs:131 +/// Passes as const to: mbedtls_ecp_check_privkey / mbedtls_ecp_check_pubkey / mbedtls_ecp_get_type( grp +/// +/// - Ignored due to not defined: ecdsa_verify_rs_wrap, ecdsa_sign_rs_wrap, ecdsa_rs_alloc, ecdsa_rs_free +/// (Undefined - MBEDTLS_ECP_RESTARTABLE - ../../../mbedtls-sys/build/config.rs:173) +/// +/// - Only const access to context: eckey_check_pair +/// +/// - Only used when creating/freeing - which is safe by design: ecdsa_alloc_wrap, ecdsa_free_wrap +/// +#[cfg(feature = "threading")] +unsafe impl Sync for Pk {} + impl Pk { /// Takes both DER and PEM forms of PKCS#1 or PKCS#8 encoded keys. /// @@ -323,11 +415,13 @@ impl Pk { .is_ok() } - getter!( - /// Key length in bits - len() -> usize = fn pk_get_bitlen - ); - getter!(pk_type() -> Type = fn pk_get_type); + pub fn len(&self) -> usize { + unsafe { pk_get_bitlen(&self.inner) } + } + + pub fn pk_type(&self) -> Type { + unsafe { pk_get_type(&self.inner).into() } + } pub fn curve(&self) -> Result { match self.pk_type() { @@ -692,7 +786,7 @@ impl Pk { sig: &mut [u8], rng: &mut F, ) -> Result { - use crate::rng::RngCallback; + use crate::rng::RngCallbackMut; if self.pk_type() == Type::Ecdsa || self.pk_type() == Type::Eckey { if sig.len() < ECDSA_MAX_LEN { @@ -717,8 +811,8 @@ impl Pk { hash.len(), sig.as_mut_ptr(), &mut ret, - Some(Rfc6979Rng::call), - rng.data_ptr(), + Some(Rfc6979Rng::call_mut), + rng.data_ptr_mut(), ).into_result()?; }; Ok(ret) diff --git a/mbedtls/src/pk/rfc6979.rs b/mbedtls/src/pk/rfc6979.rs index 1bc42f134..30da45d62 100644 --- a/mbedtls/src/pk/rfc6979.rs +++ b/mbedtls/src/pk/rfc6979.rs @@ -12,7 +12,7 @@ use crate::alloc_prelude::*; use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void}; use mbedtls_sys::types::size_t; -use crate::rng::{HmacDrbg, Random, RngCallback}; +use crate::rng::{HmacDrbg, Random, RngCallbackMut}; use crate::error::Result; use crate::bignum::Mpi; @@ -67,7 +67,7 @@ fn generate_rfc6979_nonce(md: &MdInfo, x: &Mpi, q: &Mpi, digest_bytes: &[u8]) -> pub(crate) struct Rfc6979Rng { pub k: Vec, pub k_read: usize, - pub rng: HmacDrbg<'static>, + pub rng: HmacDrbg, } /// An RNG which first outputs the k for RFC 6797 followed by random data @@ -110,8 +110,8 @@ impl Rfc6979Rng { } } -impl RngCallback for Rfc6979Rng { - unsafe extern "C" fn call( +impl RngCallbackMut for Rfc6979Rng { + unsafe extern "C" fn call_mut( user_data: *mut c_void, data_ptr: *mut c_uchar, len: size_t, @@ -126,7 +126,7 @@ impl RngCallback for Rfc6979Rng { } } - fn data_ptr(&mut self) -> *mut c_void { + fn data_ptr_mut(&mut self) -> *mut c_void { self as *const _ as *mut _ } } diff --git a/mbedtls/src/rng/ctr_drbg.rs b/mbedtls/src/rng/ctr_drbg.rs index 1b4184ba2..ffc062c01 100644 --- a/mbedtls/src/rng/ctr_drbg.rs +++ b/mbedtls/src/rng/ctr_drbg.rs @@ -6,126 +6,77 @@ * option. This file may not be copied, modified, or distributed except * according to those terms. */ +use mbedtls_sys::*; +use std::sync::Arc; use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void}; use mbedtls_sys::types::size_t; pub use mbedtls_sys::CTR_DRBG_RESEED_INTERVAL as RESEED_INTERVAL; -use mbedtls_sys::{ - ctr_drbg_random, ctr_drbg_reseed, ctr_drbg_seed, ctr_drbg_set_prediction_resistance, - ctr_drbg_update, CTR_DRBG_PR_OFF, CTR_DRBG_PR_ON, -}; - -use super::{EntropyCallback, RngCallback}; use crate::error::{IntoResult, Result}; +use crate::rng::{EntropyCallback, RngCallback, RngCallbackMut}; + +#[allow(dead_code)] +pub struct CtrDrbg { + // Moving data causes dangling pointers: https://github.com/ARMmbed/mbedtls/issues/2147 + // Storing data in heap and forcing rust move to only move the pointer (box) referencing it. + // The move will be faster. Access to data will be slower due to additional indirection. + inner: Box, + entropy: Arc, +} -// ==== BEGIN IMMOVABLE TYPE KLUDGE ==== -// `ctr_drbg_context` inlines an `aes_context`, which is immovable. See -// https://github.com/ARMmbed/mbedtls/issues/2147. We work around this -// by always boxing up the context, which requires this module to depend on -// std/alloc. -// -// If `ctr_drbg_context` were moveable, this entire section could be replaced -// by basically: -// ``` -// define!( -// #[c_ty(ctr_drbg_context)] -// struct CtrDrbg<'entropy>; -// fn init() { -// ctr_drbg_init -// } -// fn drop() { -// ctr_drbg_free -// } -// ); -// ``` - -use self::private::CtrDrbgInner; -#[cfg(not(feature = "std"))] -use crate::alloc_prelude::*; -use core::ops::{Deref, DerefMut}; - -mod private { - use core::marker::PhantomData; - use mbedtls_sys::{ctr_drbg_context, ctr_drbg_free, ctr_drbg_init}; - - pub struct CtrDrbgInner<'entropy> { - pub(super) inner: ctr_drbg_context, - r: PhantomData<&'entropy ()>, - } - - impl<'entropy> CtrDrbgInner<'entropy> { - pub(super) fn init() -> Self { - let mut inner = ::core::mem::MaybeUninit::uninit(); - let inner = unsafe { - ctr_drbg_init(inner.as_mut_ptr()); - inner.assume_init() - }; - CtrDrbgInner { - inner, - r: PhantomData, - } - } - } +#[cfg(feature = "threading")] +unsafe impl Send for CtrDrbg {} + +/// +/// Class has interior mutability via function called 'call'. +/// That function has an internal mutex to guarantee thread safety. +/// +/// The other potential conflict is a mutable reference changing class. +/// That is avoided by having any users of the callback hold an 'Arc' to this class. +/// Rust will then ensure that a mutable reference cannot be aquired if more then 1 Arc exists to the same class. +/// +#[cfg(feature = "threading")] +unsafe impl Sync for CtrDrbg {} - impl<'entropy> Drop for CtrDrbgInner<'entropy> { - fn drop(&mut self) { - unsafe { ctr_drbg_free(&mut self.inner) }; - } - } -} +#[allow(dead_code)] +impl CtrDrbg { -pub struct CtrDrbg<'entropy> { - boxed: Box>, -} + // If threading enabled - we are Sync, but for that to be true we need entropy to also be sync. + #[cfg(feature = "threading")] + pub fn new(entropy: Arc, additional_entropy: Option<&[u8]>) -> Result { + let mut inner = Box::new(ctr_drbg_context::default()); -impl<'entropy> CtrDrbg<'entropy> { - fn init() -> Self { - CtrDrbg { - boxed: Box::new(CtrDrbgInner::init()), + unsafe { + ctr_drbg_init(&mut *inner); + ctr_drbg_seed( + &mut *inner, + Some(T::call), + entropy.data_ptr(), + additional_entropy.map(<[_]>::as_ptr).unwrap_or(::core::ptr::null()), + additional_entropy.map(<[_]>::len).unwrap_or(0) + ).into_result()?; } - } -} -#[doc(hidden)] -impl<'entropy> Deref for CtrDrbg<'entropy> { - type Target = CtrDrbgInner<'entropy>; - fn deref(&self) -> &Self::Target { - &self.boxed + Ok(CtrDrbg { inner, entropy }) } -} -#[doc(hidden)] -impl<'entropy> DerefMut for CtrDrbg<'entropy> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.boxed - } -} - -// ==== END IMMOVABLE TYPE KLUDGE ==== + #[cfg(not(feature = "threading"))] + pub fn new(entropy: Arc, additional_entropy: Option<&[u8]>) -> Result { + let mut inner = Box::new(ctr_drbg_context::default()); -#[cfg(feature = "threading")] -unsafe impl<'entropy> Sync for CtrDrbg<'entropy> {} - -impl<'entropy> CtrDrbg<'entropy> { - pub fn new( - source: &'entropy mut F, - additional_entropy: Option<&[u8]>, - ) -> Result> { - let mut ret = Self::init(); unsafe { + ctr_drbg_init(&mut *inner); ctr_drbg_seed( - &mut ret.inner, - Some(F::call), - source.data_ptr(), - additional_entropy - .map(<[_]>::as_ptr) - .unwrap_or(::core::ptr::null()), + &mut *inner, + Some(T::call), + entropy.data_ptr(), + additional_entropy.map(<[_]>::as_ptr).unwrap_or(::core::ptr::null()), additional_entropy.map(<[_]>::len).unwrap_or(0) - ) - .into_result()? - }; - Ok(ret) - } + ).into_result()?; + } + Ok(CtrDrbg { inner, entropy }) + } + pub fn prediction_resistance(&self) -> bool { if self.inner.prediction_resistance == CTR_DRBG_PR_OFF { false @@ -137,21 +88,32 @@ impl<'entropy> CtrDrbg<'entropy> { pub fn set_prediction_resistance(&mut self, pr: bool) { unsafe { ctr_drbg_set_prediction_resistance( - &mut self.inner, + &mut *self.inner, if pr { CTR_DRBG_PR_ON } else { CTR_DRBG_PR_OFF }, ) } } - getter!(entropy_len() -> size_t = .entropy_len); - setter!(set_entropy_len(len: size_t) = ctr_drbg_set_entropy_len); - getter!(reseed_interval() -> c_int = .reseed_interval); - setter!(set_reseed_interval(i: c_int) = ctr_drbg_set_reseed_interval); + pub fn entropy_len(&self) -> size_t { + self.inner.entropy_len + } + + pub fn set_entropy_len(&mut self, len: size_t) { + unsafe { ctr_drbg_set_entropy_len(&mut *self.inner, len); } + } + + pub fn reseed_interval(&self) -> c_int { + self.inner.reseed_interval + } + + pub fn set_reseed_interval(&mut self, i: c_int) { + unsafe { ctr_drbg_set_reseed_interval(&mut *self.inner, i); } + } pub fn reseed(&mut self, additional_entropy: Option<&[u8]>) -> Result<()> { unsafe { ctr_drbg_reseed( - &mut self.inner, + &mut *self.inner, additional_entropy .map(<[_]>::as_ptr) .unwrap_or(::core::ptr::null()), @@ -163,24 +125,37 @@ impl<'entropy> CtrDrbg<'entropy> { } pub fn update(&mut self, entropy: &[u8]) { - unsafe { ctr_drbg_update(&mut self.inner, entropy.as_ptr(), entropy.len()) }; + unsafe { ctr_drbg_update(&mut *self.inner, entropy.as_ptr(), entropy.len()) }; } +} - // TODO: - // - // ctr_drbg_random_with_add - // ctr_drbg_write_seed_file - // ctr_drbg_update_seed_file - // +#[allow(dead_code)] +impl Drop for CtrDrbg { + fn drop(&mut self) { + unsafe { ctr_drbg_free(&mut *self.inner) }; + } } -impl<'entropy> RngCallback for CtrDrbg<'entropy> { +impl RngCallbackMut for CtrDrbg { #[inline(always)] - unsafe extern "C" fn call(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { + unsafe extern "C" fn call_mut(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int where Self: std::marker::Sized { + // Mutex used in ctr_drbg_random at: ../../../mbedtls-sys/vendor/crypto/library/ctr_drbg.c:546 ctr_drbg_random(user_data, data, len) } - fn data_ptr(&mut self) -> *mut c_void { - &mut self.inner as *mut _ as *mut _ + fn data_ptr_mut(&mut self) -> *mut c_void { + &*self.inner as *const _ as *mut _ + } +} + +impl RngCallback for CtrDrbg { + #[inline(always)] + unsafe extern "C" fn call(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int where Self: std::marker::Sized { + // Mutex used in ctr_drbg_random at: ../../../mbedtls-sys/vendor/crypto/library/ctr_drbg.c:546 + ctr_drbg_random(user_data, data, len) + } + + fn data_ptr(&self) -> *mut c_void { + &*self.inner as *const _ as *mut _ } } diff --git a/mbedtls/src/rng/hmac_drbg.rs b/mbedtls/src/rng/hmac_drbg.rs index 5320dd672..e97e98aaa 100644 --- a/mbedtls/src/rng/hmac_drbg.rs +++ b/mbedtls/src/rng/hmac_drbg.rs @@ -9,41 +9,51 @@ use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void}; use mbedtls_sys::types::size_t; pub use mbedtls_sys::HMAC_DRBG_RESEED_INTERVAL as RESEED_INTERVAL; -use mbedtls_sys::{ - hmac_drbg_random, hmac_drbg_reseed, hmac_drbg_seed, hmac_drbg_seed_buf, - hmac_drbg_set_prediction_resistance, hmac_drbg_update, HMAC_DRBG_PR_OFF, HMAC_DRBG_PR_ON, -}; +use mbedtls_sys::*; -use super::{EntropyCallback, RngCallback}; +use crate::rng::{EntropyCallback, RngCallback, RngCallbackMut}; use crate::error::{IntoResult, Result}; use crate::hash::MdInfo; +use std::sync::Arc; -define!( - #[c_ty(hmac_drbg_context)] - struct HmacDrbg<'entropy>; - const init: fn() -> Self = hmac_drbg_init; - const drop: fn(&mut Self) = hmac_drbg_free; -); +#[allow(dead_code)] +pub struct HmacDrbg { + inner: hmac_drbg_context, + entropy: Option>, +} + +unsafe impl Send for HmacDrbg {} #[cfg(feature = "threading")] -unsafe impl<'entropy> Sync for HmacDrbg<'entropy> {} +unsafe impl Sync for HmacDrbg {} -impl<'entropy> HmacDrbg<'entropy> { - pub fn new( +#[allow(dead_code)] +impl Drop for HmacDrbg { + fn drop(&mut self) { + unsafe { hmac_drbg_free(&mut self.inner) }; + } +} + +impl HmacDrbg { + pub fn new( md_info: MdInfo, - source: &'entropy mut F, + entropy: Arc, additional_entropy: Option<&[u8]>, - ) -> Result> { - let mut ret = Self::init(); + ) -> Result { + + let mut ret = HmacDrbg { + inner: hmac_drbg_context::default(), + entropy: Some(entropy), + }; + unsafe { + hmac_drbg_init(&mut ret.inner); hmac_drbg_seed( &mut ret.inner, md_info.into(), - Some(F::call), - source.data_ptr(), - additional_entropy - .map(<[_]>::as_ptr) - .unwrap_or(::core::ptr::null()), + Some(T::call), + ret.entropy.as_ref().unwrap().data_ptr(), + additional_entropy.map(<[_]>::as_ptr).unwrap_or(::core::ptr::null()), additional_entropy.map(<[_]>::len).unwrap_or(0) ) .into_result()? @@ -51,9 +61,15 @@ impl<'entropy> HmacDrbg<'entropy> { Ok(ret) } - pub fn from_buf(md_info: MdInfo, entropy: &[u8]) -> Result> { - let mut ret = Self::init(); + + pub fn from_buf(md_info: MdInfo, entropy: &[u8]) -> Result { + let mut ret = HmacDrbg { + inner: hmac_drbg_context::default(), + entropy: None, + }; + unsafe { + hmac_drbg_init(&mut ret.inner); hmac_drbg_seed_buf( &mut ret.inner, md_info.into(), @@ -86,10 +102,21 @@ impl<'entropy> HmacDrbg<'entropy> { } } - getter!(entropy_len() -> size_t = .entropy_len); - setter!(set_entropy_len(len: size_t) = hmac_drbg_set_entropy_len); - getter!(reseed_interval() -> c_int = .reseed_interval); - setter!(set_reseed_interval(i: c_int) = hmac_drbg_set_reseed_interval); + pub fn entropy_len(&self) -> size_t { + self.inner.entropy_len + } + + pub fn set_entropy_len(&mut self, len: size_t) { + unsafe { hmac_drbg_set_entropy_len(&mut self.inner, len); } + } + + pub fn reseed_interval(&self) -> c_int { + self.inner.reseed_interval + } + + pub fn set_reseed_interval(&mut self, i: c_int) { + unsafe { hmac_drbg_set_reseed_interval(&mut self.inner, i); } + } pub fn reseed(&mut self, additional_entropy: Option<&[u8]>) -> Result<()> { unsafe { @@ -117,13 +144,26 @@ impl<'entropy> HmacDrbg<'entropy> { // } -impl<'entropy> RngCallback for HmacDrbg<'entropy> { +impl RngCallbackMut for HmacDrbg { + #[inline(always)] + unsafe extern "C" fn call_mut(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { + // Mutex used in hmac_drbg_random: ../../../mbedtls-sys/vendor/crypto/library/hmac_drbg.c:363 + hmac_drbg_random(user_data, data, len) + } + + fn data_ptr_mut(&mut self) -> *mut c_void { + &self.inner as *const _ as *mut _ + } +} + +impl RngCallback for HmacDrbg { #[inline(always)] unsafe extern "C" fn call(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { + // Mutex used in hmac_drbg_random: ../../../mbedtls-sys/vendor/crypto/library/hmac_drbg.c:363 hmac_drbg_random(user_data, data, len) } - fn data_ptr(&mut self) -> *mut c_void { - &mut self.inner as *mut _ as *mut _ + fn data_ptr(&self) -> *mut c_void { + &self.inner as *const _ as *mut _ } } diff --git a/mbedtls/src/rng/mod.rs b/mbedtls/src/rng/mod.rs index 364ac3b7a..25d18c972 100644 --- a/mbedtls/src/rng/mod.rs +++ b/mbedtls/src/rng/mod.rs @@ -21,17 +21,17 @@ pub use self::hmac_drbg::HmacDrbg; #[doc(inline)] pub use self::os_entropy::OsEntropy; #[cfg(feature = "rdrand")] -pub use self::rdrand::{Entropy as Rdseed, Nrbg as Rdrand}; +pub use self::rdrand::{Rdseed, Rdrand}; use crate::error::{Result, IntoResult}; use mbedtls_sys::types::raw_types::{c_int, c_uchar}; use mbedtls_sys::types::size_t; -callback!(EntropyCallback:Sync(data: *mut c_uchar, len: size_t) -> c_int); -callback!(RngCallback:Sync(data: *mut c_uchar, len: size_t) -> c_int); +callback!(EntropyCallbackMut,EntropyCallback:Sync(data: *mut c_uchar, len: size_t) -> c_int); +callback!(RngCallbackMut,RngCallback:Sync(data: *mut c_uchar, len: size_t) -> c_int); pub trait Random: RngCallback { - fn random(&mut self, data: &mut [u8]) -> Result<()> { + fn random(&mut self, data: &mut [u8]) -> Result<()> where Self: std::marker::Sized { unsafe { Self::call(self.data_ptr(), data.as_mut_ptr(), data.len()) }.into_result()?; Ok(()) } diff --git a/mbedtls/src/rng/os_entropy.rs b/mbedtls/src/rng/os_entropy.rs index ec1e333d4..bffd6298c 100644 --- a/mbedtls/src/rng/os_entropy.rs +++ b/mbedtls/src/rng/os_entropy.rs @@ -6,71 +6,127 @@ * option. This file may not be copied, modified, or distributed except * according to those terms. */ +use crate::error::{IntoResult, Result}; +use crate::rng::EntropyCallback; +use mbedtls_sys::*; use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void}; use mbedtls_sys::types::size_t; -use mbedtls_sys::*; +use std::sync::Arc; -use crate::error::{IntoResult, Result}; +callback!(EntropySourceCallbackMut,EntropySourceCallback(data: *mut c_uchar, size: size_t, out: *mut size_t) -> c_int); + +#[allow(dead_code)] +pub struct OsEntropy { + // Moving data causes dangling pointers: https://github.com/ARMmbed/mbedtls/issues/2147 + // Storing data in heap and forcing rust move to only move the pointer (box) referencing it. + // The move will be faster. Access to data will be slower due to additional indirection. + inner: Box, + sources: Vec>, +} + +impl Into<*mut mbedtls_sys::entropy_context> for &mut OsEntropy { + fn into(self) -> *mut mbedtls_sys::entropy_context { + &mut *self.inner + } +} + +impl Into<*const mbedtls_sys::entropy_context> for &mut OsEntropy { + fn into(self) -> *const mbedtls_sys::entropy_context { + &*self.inner + } +} + +impl Into<*const mbedtls_sys::entropy_context> for &OsEntropy { + fn into(self) -> *const mbedtls_sys::entropy_context { + &*self.inner + } +} -callback!(EntropySourceCallback(data: *mut c_uchar, size: size_t, out: *mut size_t) -> c_int); -define!( - #[c_ty(entropy_context)] - struct OsEntropy<'source>; - pub const new: fn() -> Self = entropy_init; - const drop: fn(&mut Self) = entropy_free; -); +unsafe impl Send for OsEntropy {} +/// +/// Class has interior mutability via function called 'call'. +/// That function has an internal mutex to guarantee thread safety. +/// +/// The other potential conflict is a mutable reference changing class. +/// That is avoided by having any users of the callback hold an 'Arc' to this class. +/// Rust will then ensure that a mutable reference cannot be aquired if more then 1 Arc exists to the same class. +/// #[cfg(feature = "threading")] -unsafe impl<'source> Sync for OsEntropy<'source> {} +unsafe impl Sync for OsEntropy {} -impl<'source> OsEntropy<'source> { - pub fn add_source( +#[allow(dead_code)] +impl OsEntropy { + + pub fn new() -> Self { + let mut inner = Box::new(entropy_context::default()); + + unsafe { + entropy_init(&mut *inner); + }; + + OsEntropy { + inner, + sources: vec![], + } + } + + pub fn add_source( &mut self, - source: &'source mut F, + source: Arc, threshold: size_t, strong: bool, ) -> Result<()> { unsafe { + // add_source is guarded with internal mutex: mbedtls-sys/vendor/crypto/library/entropy.c:143 + // all sources are called at later points via 'entropy_gather_internal' which in turn is called with internal mutex locked. entropy_add_source( - &mut self.inner, + self.into(), Some(F::call), source.data_ptr(), threshold, - if strong { - ENTROPY_SOURCE_STRONG - } else { - ENTROPY_SOURCE_WEAK - } + if strong { ENTROPY_SOURCE_STRONG } else { ENTROPY_SOURCE_WEAK } ) .into_result()? }; + + // Rust ensures only one mutable reference is currently in use. + self.sources.push(source); Ok(()) } - pub fn gather(&mut self) -> Result<()> { - unsafe { entropy_gather(&mut self.inner) }.into_result()?; + pub fn update_manual(&mut self, data: &[u8]) -> Result<()> { + // function is guarded with internal mutex: mbedtls-sys/vendor/crypto/library/entropy.c:241 + unsafe { entropy_update_manual(self.into(), data.as_ptr(), data.len()) }.into_result()?; Ok(()) } - pub fn update_manual(&mut self, data: &[u8]) -> Result<()> { - unsafe { entropy_update_manual(&mut self.inner, data.as_ptr(), data.len()) }.into_result()?; + pub fn gather(&mut self) -> Result<()> { + // function is guarded with internal mutex: mbedtls-sys/vendor/crypto/library/entropy.c:310 + unsafe { entropy_gather(self.into()) }.into_result()?; Ok(()) } - // TODO - // entropy_write_seed_file - // entropy_update_seed_file - // } -impl<'source> super::EntropyCallback for OsEntropy<'source> { +#[allow(dead_code)] +impl Drop for OsEntropy { + fn drop(&mut self) { + unsafe { entropy_free(self.into()); } + } +} + + +impl EntropyCallback for OsEntropy { #[inline(always)] unsafe extern "C" fn call(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { + // mutex used in entropy_func: ../../../mbedtls-sys/vendor/crypto/library/entropy.c:348 + // note: we're not using MBEDTLS_ENTROPY_NV_SEED so the initialization is not present or a race condition. entropy_func(user_data, data, len) } - fn data_ptr(&mut self) -> *mut c_void { - &mut self.inner as *mut _ as *mut _ + fn data_ptr(&self) -> *mut c_void { + &*self.inner as *const _ as *mut _ } } diff --git a/mbedtls/src/rng/rdrand.rs b/mbedtls/src/rng/rdrand.rs index 9b734a6b7..04abfe4f5 100644 --- a/mbedtls/src/rng/rdrand.rs +++ b/mbedtls/src/rng/rdrand.rs @@ -64,30 +64,47 @@ fn write_rng_to_slice(outbuf: &mut [u8], rng: fn() -> Option) -> c_int { 0 } -use super::{EntropyCallback, RngCallback}; +use super::{EntropyCallback, RngCallback, RngCallbackMut}; -pub struct Entropy; +pub struct Rdseed; -impl EntropyCallback for Entropy { +impl EntropyCallback for Rdseed { unsafe extern "C" fn call(_: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { let mut outbuf = from_raw_parts_mut(data, len); write_rng_to_slice(&mut outbuf, rdseed) } - fn data_ptr(&mut self) -> *mut c_void { + fn data_ptr(&self) -> *mut c_void { ::core::ptr::null_mut() } } -pub struct Nrbg; +pub struct Rdrand; -impl RngCallback for Nrbg { +unsafe impl RngCallbackMut for Rdrand { unsafe extern "C" fn call(_: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { + // outbuf data/len are stack variables let mut outbuf = from_raw_parts_mut(data, len); + + // rdrand function is thread safe write_rng_to_slice(&mut outbuf, rdrand) } - fn data_ptr(&mut self) -> *mut c_void { + fn data_ptr_mut(&mut self) -> *mut c_void { ::core::ptr::null_mut() } } + +impl RngCallback for Rdrand { + unsafe extern "C" fn call(_: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { + // outbuf data/len are stack variables + let mut outbuf = from_raw_parts_mut(data, len); + + // rdrand function is thread safe + write_rng_to_slice(&mut outbuf, rdrand) + } + + fn data_ptr(&self) -> *mut c_void { + ::core::ptr::null_mut() + } +} \ No newline at end of file diff --git a/mbedtls/src/rust_malloc.c b/mbedtls/src/rust_malloc.c new file mode 100644 index 000000000..fdf487b9f --- /dev/null +++ b/mbedtls/src/rust_malloc.c @@ -0,0 +1,29 @@ +/* Copyright (c) Fortanix, Inc. + * + * Licensed under the GNU General Public License, version 2 or the Apache License, Version + * 2.0 , at your + * option. This file may not be copied, modified, or distributed except + * according to those terms. */ + +// Follow same pattern for config and alloc/free as everywhere in mbedtls +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +extern void *forward_mbedtls_calloc( size_t n, size_t size ) { + return mbedtls_calloc(n, size); +} +extern void forward_mbedtls_free( void *ptr ) { + mbedtls_free(ptr); +} \ No newline at end of file diff --git a/mbedtls/src/self_test.rs b/mbedtls/src/self_test.rs index 3a97b2244..ff2229606 100644 --- a/mbedtls/src/self_test.rs +++ b/mbedtls/src/self_test.rs @@ -58,6 +58,11 @@ pub unsafe fn disable() { log_f = None; } +// +// NOTE: The following functions if used in a multithreaded or async environment will fail. +// Self test functions rely on global variables to track operations and anything non-self-test related will stomp over variables. +// While using these, make sure no other code uses mbedtls. Multiple self test operations done asynchronously may also return failures. +// pub use mbedtls_sys::{ aes_self_test as aes, arc4_self_test as arc4, base64_self_test as base64, camellia_self_test as camellia, ccm_self_test as ccm, ctr_drbg_self_test as ctr_drbg, diff --git a/mbedtls/src/ssl/ciphersuites.rs b/mbedtls/src/ssl/ciphersuites.rs index 20cbeaac8..a0b39df03 100644 --- a/mbedtls/src/ssl/ciphersuites.rs +++ b/mbedtls/src/ssl/ciphersuites.rs @@ -9,6 +9,7 @@ use mbedtls_sys::types::raw_types::c_int; use mbedtls_sys::*; +/// Always use into() to convert to i32, do not use 'as i32'. (until issue is fixed: https://github.com/fortanix/rust-mbedtls/issues/129) define!( #[non_exhaustive] #[c_ty(c_int)] diff --git a/mbedtls/src/ssl/config.rs b/mbedtls/src/ssl/config.rs index 936d047db..ad1c960b6 100644 --- a/mbedtls/src/ssl/config.rs +++ b/mbedtls/src/ssl/config.rs @@ -6,20 +6,24 @@ * option. This file may not be copied, modified, or distributed except * according to those terms. */ -use core::slice::from_raw_parts; - -use mbedtls_sys::types::raw_types::{c_char, c_int, c_uchar, c_uint, c_void}; -use mbedtls_sys::types::size_t; -use mbedtls_sys::*; - -use crate::error::{Error, IntoResult, Result}; -use core::result::Result as StdResult; -use crate::pk::dhparam::Dhm; +use crate::error::{Error, Result, IntoResult}; use crate::pk::Pk; -use crate::private::UnsafeFrom; +use crate::rng::RngCallback; +use mbedtls_sys::*; +use mbedtls_sys::types::raw_types::{c_int, c_void, c_char, c_uchar, c_uint}; +use std::sync::Arc; +use crate::x509::Crl; +use crate::x509::Certificate; +use crate::x509::VerifyError; use crate::ssl::context::HandshakeContext; +use mbedtls_sys::types::size_t; +use std::slice::from_raw_parts; use crate::ssl::ticket::TicketCallback; -use crate::x509::{certificate, Crl, LinkedCertificate, Profile, VerifyError}; +use crate::pk::dhparam::Dhm; +use crate::x509::Profile; +use crate::ssl::Context; +use crate::private::UnsafeFrom; +use crate::x509::certificate::MbedtlsList; extern "C" { fn calloc(n: usize, size: usize) -> *mut c_void; @@ -83,57 +87,163 @@ define!( } ); -callback!(DbgCallback:Sync(level: c_int, file: *const c_char, line: c_int, message: *const c_char) -> ()); - define!( - #[c_ty(ssl_config)] - struct Config<'c>; - const init: fn() -> Self = ssl_config_init; - const drop: fn(&mut Self) = ssl_config_free; - impl<'q> Into {} - impl<'q> UnsafeFrom {} + #[c_ty(c_int)] + enum Renegotiation { + Enabled = SSL_RENEGOTIATION_ENABLED, + Disabled = SSL_RENEGOTIATION_DISABLED, + } ); + + +pub struct Config { + // Moving data may cause dangling pointers: https://github.com/ARMmbed/mbedtls/issues/2147 + // Storing data in heap and forcing rust move to only move the pointer (box) referencing it. + inner: Box, + + // Holding reference counters against any structures that ssl_config might hold pointer to. + // This allows caller to share structure on multiple configs if needed. + own_cert: Vec>>, + own_pk: Vec>, + + ca_cert: Option>>, + crl: Option>, + + // If we are sync we need all members to be sync, as such need to use cfg feature on all callbacks. + #[cfg(feature = "threading")] + rng: Option>, + #[cfg(not (feature = "threading"))] + rng: Option>, + + ciphersuites: Vec>>, + curves: Option>>, + + #[allow(dead_code)] + dhm: Option>, + + #[cfg(feature = "threading")] + verify_callback: Option Result<()>) + Send + Sync + 'static>>, + #[cfg(not (feature = "threading"))] + verify_callback: Option Result<()>) + 'static>>, + + #[cfg(feature = "threading")] + dbg_callback: Option ()) + Send + Sync + 'static>>, + #[cfg(not (feature = "threading"))] + dbg_callback: Option ()) + 'static>>, + + #[cfg(feature = "threading")] + sni_callback: Option Result<()>) + Send + Sync + 'static>>, + #[cfg(not (feature = "threading"))] + sni_callback: Option Result<()>) + 'static>>, + + #[cfg(feature = "threading")] + ticket_callback: Option>, + #[cfg(not (feature = "threading"))] + ticket_callback: Option>, + + #[cfg(feature = "threading")] + ca_callback: Option Result<()>) + Send + Sync + 'static>>, + #[cfg(not (feature = "threading"))] + ca_callback: Option Result<()>) + 'static>>, + +} + +#[cfg(feature = "threading")] +unsafe impl Sync for Config {} + #[cfg(feature = "threading")] -unsafe impl<'c> Sync for Config<'c> {} +unsafe impl Send for Config {} + +impl Into<*mut mbedtls_sys::ssl_config> for &mut Config { + fn into(self) -> *mut mbedtls_sys::ssl_config { + &mut *self.inner + } +} + -impl<'c> Config<'c> { +impl Into<*const mbedtls_sys::ssl_config> for &Config { + fn into(self) -> *const mbedtls_sys::ssl_config { + &*self.inner + } +} + +impl Config { pub fn new(e: Endpoint, t: Transport, p: Preset) -> Self { - let mut c = Config::init(); + let mut inner = Box::new(ssl_config::default()); + unsafe { - ssl_config_defaults(&mut c.inner, e.into(), t.into(), p.into()); + // This is just a memset to 0. + ssl_config_init(&mut *inner); + + // Set default values - after this point we will need ssl_config_free to be called. + ssl_config_defaults(&mut *inner, e as c_int, t as c_int, p as c_int); + }; + + Config { + inner, + own_cert: vec![], + own_pk: vec![], + ca_cert: None, + crl: None, + rng: None, + ciphersuites: vec![], + curves: None, + dhm: None, + verify_callback: None, + dbg_callback: None, + sni_callback: None, + ticket_callback: None, + ca_callback: None, } - c } - // need bitfield support getter!(endpoint() -> Endpoint = field endpoint); - setter!(set_endpoint(e: Endpoint) = ssl_conf_endpoint); - // need bitfield support getter!(transport() -> Transport = field transport); - setter!(set_transport(t: Transport) = ssl_conf_transport); - // need bitfield support getter!(authmode() -> AuthMode = field authmode); - setter!(set_authmode(am: AuthMode) = ssl_conf_authmode); - getter!(read_timeout() -> u32 = .read_timeout); - setter!(set_read_timeout(t: u32) = ssl_conf_read_timeout); + pub fn set_authmode(&mut self, authmode: AuthMode) { + unsafe { ssl_conf_authmode(self.into(), authmode as c_int); } + } + + pub fn read_timeout(&self) -> u32 { + self.inner.read_timeout + } + + pub fn set_read_timeout(&mut self, t: u32) { + unsafe { ssl_conf_read_timeout(self.into(), t); } + } fn check_c_list(list: &[T]) { assert!(list.last() == Some(&T::default())); } - pub fn set_ciphersuites(&mut self, list: &'c [c_int]) { - Self::check_c_list(list); - unsafe { ssl_conf_ciphersuites(&mut self.inner, list.as_ptr()) } + pub fn set_ciphersuites(&mut self, list: Arc>) { + Self::check_c_list(&list); + + unsafe { ssl_conf_ciphersuites(self.into(), (*Arc::as_ptr(&list)).as_ptr()) } + self.ciphersuites.push(list); } - pub fn set_ciphersuites_for_version(&mut self, list: &'c [c_int], major: c_int, minor: c_int) { - Self::check_c_list(list); - unsafe { ssl_conf_ciphersuites_for_version(&mut self.inner, list.as_ptr(), major, minor) } + pub fn set_ciphersuites_for_version(&mut self, list: Arc>, major: c_int, minor: c_int) { + Self::check_c_list(&list); + unsafe { ssl_conf_ciphersuites_for_version(self.into(), (*Arc::as_ptr(&list)).as_ptr(), major, minor) } + self.ciphersuites.push(list); } - pub fn set_curves(&mut self, list: &'c [ecp_group_id]) { - Self::check_c_list(list); - unsafe { ssl_conf_curves(&mut self.inner, list.as_ptr()) } + pub fn set_curves(&mut self, list: Arc>) { + Self::check_c_list(&list); + unsafe { ssl_conf_curves(self.into(), (*Arc::as_ptr(&list)).as_ptr()) } + self.curves = Some(list); } + #[cfg(feature = "threading")] + pub fn set_rng(&mut self, rng: Arc) { + unsafe { ssl_conf_rng(self.into(), Some(T::call), rng.data_ptr()) }; + self.rng = Some(rng); + } + #[cfg(not (feature = "threading"))] + pub fn set_rng(&mut self, rng: Arc) { + unsafe { ssl_conf_rng(self.into(), Some(T::call), rng.data_ptr()) }; + self.rng = Some(rng); + } + pub fn set_min_version(&mut self, version: Version) -> Result<()> { let minor = match version { Version::Ssl3 => 0, @@ -143,7 +253,7 @@ impl<'c> Config<'c> { _ => { return Err(Error::SslBadHsProtocolVersion); } }; - unsafe { ssl_conf_min_version(&mut self.inner, 3, minor) }; + unsafe { ssl_conf_min_version(self.into(), 3, minor) }; Ok(()) } @@ -155,186 +265,194 @@ impl<'c> Config<'c> { Version::Tls1_2 => 3, _ => { return Err(Error::SslBadHsProtocolVersion); } }; - unsafe { ssl_conf_max_version(&mut self.inner, 3, minor) }; + unsafe { ssl_conf_max_version(self.into(), 3, minor) }; Ok(()) } - setter!(set_cert_profile(p: &'c Profile) = ssl_conf_cert_profile); + // Profile as implemented in profile.rs can only point to global variables from mbedtls which would have 'static lifetime + pub fn set_cert_profile(&mut self, p: &'static Profile) { + unsafe { ssl_conf_cert_profile(self.into(), p.into()) }; + } /// Takes both DER and PEM forms of FFDH parameters in `DHParams` format. /// /// When calling on PEM-encoded data, `params` must be NULL-terminated pub fn set_dh_params(&mut self, params: &[u8]) -> Result<()> { - let mut ctx = Dhm::from_params(params)?; + let dhm = Arc::new(Dhm::from_params(params)?); unsafe { - ssl_conf_dh_param_ctx(&mut self.inner, (&mut ctx).into()) + ssl_conf_dh_param_ctx(self.into(), (&*dhm).into()) .into_result() - .map(|_| ()) + .map(|_| ())?; } + self.dhm = Some(dhm); + Ok(()) } - pub fn set_ca_list>( - &mut self, - list: Option, - crl: Option<&'c mut Crl>, - ) { - unsafe { - ssl_conf_ca_chain( - &mut self.inner, - list.map(Into::into) - .map(Into::into) - .unwrap_or(::core::ptr::null_mut()), - crl.map(Into::into).unwrap_or(::core::ptr::null_mut()), - ) - } - } + pub fn set_ca_list(&mut self, ca_cert: Arc>, crl: Option>) { + // This will override internal pointers to what we provide. + + unsafe { ssl_conf_ca_chain(self.into(), (&**ca_cert).into(), crl.as_ref().map(|crl| (&(**crl)).into()).unwrap_or(::core::ptr::null_mut())); } - pub fn push_cert>( - &mut self, - chain: C, - key: &'c mut Pk, - ) -> Result<()> { - unsafe { - ssl_conf_own_cert(&mut self.inner, chain.into().into(), key.into()) - .into_result() - .map(|_| ()) - } + self.ca_cert = Some(ca_cert); + self.crl = crl; } - pub fn certs(&'c self) -> KeyCertIter<'c> { - KeyCertIter { - key_cert: unsafe { UnsafeFrom::from(self.inner.key_cert as *const _) }, + pub fn push_cert(&mut self, own_cert: Arc>, own_pk: Arc) -> Result<()> { + // Need to ensure own_cert/pk_key outlive the config. + self.own_cert.push(own_cert.clone()); + self.own_pk.push(own_pk.clone()); + + // This will append pointers to our certificates inside mbedtls + unsafe { ssl_conf_own_cert(self.into(), (&**own_cert).into(), (&*own_pk).into()) + .into_result() + .map(|_| ()) } } - + /// Server only: configure callback to use for generating/interpreting session tickets. - pub fn set_session_tickets_callback(&mut self, cb: &'c mut F) { + pub fn set_session_tickets_callback(&mut self, cb: Arc) { unsafe { ssl_conf_session_tickets_cb( - &mut self.inner, - Some(F::call_write), - Some(F::call_parse), + self.into(), + Some(T::call_write), + Some(T::call_parse), cb.data_ptr(), ) }; + + self.ticket_callback = Some(cb); + } + + pub fn set_session_tickets(&mut self, u: UseSessionTickets) { + unsafe { ssl_conf_session_tickets(self.into(), u.into()); } } - setter!( - /// Client only: whether to remember and use session tickets - set_session_tickets(u: UseSessionTickets) = ssl_conf_session_tickets - ); - - setter!( - /// Client only: minimal FFDH group size - set_ffdh_min_bitlen(bitlen: c_uint) = ssl_conf_dhm_min_bitlen - ); - - // TODO: The lifetime restrictions on HandshakeContext here are too strict. - // Once we need something else, we might fix it. - pub fn set_sni_callback StdResult<(), ()>>( - &mut self, - cb: &'c mut F, - ) { - unsafe extern "C" fn sni_callback< - F: FnMut(&mut HandshakeContext, &[u8]) -> StdResult<(), ()>, - >( + pub fn set_renegotiation(&mut self, u: Renegotiation) { + unsafe { ssl_conf_renegotiation(self.into(), u.into()); } + } + + /// Client only: minimal FFDH group size + pub fn set_ffdh_min_bitlen(&mut self, bitlen: c_uint) { + unsafe { ssl_conf_dhm_min_bitlen(self.into(), bitlen); } + } + + pub fn set_sni_callback(&mut self, cb: F) + where + F: Fn(&mut HandshakeContext, &[u8]) -> Result<()> + Send + Sync + 'static, + { + unsafe extern "C" fn sni_callback( closure: *mut c_void, ctx: *mut ssl_context, name: *const c_uchar, name_len: size_t, - ) -> c_int { + ) -> c_int + where + F: Fn(&mut HandshakeContext, &[u8]) -> Result<()> + Send + Sync + 'static, + { + // This is called from: + // + // mbedtls/src/ssl/context.rs - establish + // mbedtls-sys/vendor/library/ssl_tls.c - mbedtls_ssl_handshake + // mbedtls-sys/vendor/library/ssl_tls.c - mbedtls_ssl_handshake_step + // mbedtls-sys/vendor/library/ssl_srv.c - mbedtls_ssl_handshake_server_step + // mbedtls-sys/vendor/library/ssl_srv.c - ssl_parse_client_hello + // mbedtls-sys/vendor/library/ssl_srv.c - ssl_parse_servername_ext + // + // As such: + // - The ssl_context is a rust 'Context' structure that we have a mutable reference to via 'establish' + // - We can pointer cast to it to allow storing additional objects. + // + if closure == ::core::ptr::null_mut() || ctx == ::core::ptr::null_mut() || name == ::core::ptr::null_mut() { + return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA; + } + let cb = &mut *(closure as *mut F); - let mut ctx = UnsafeFrom::from(ctx).expect("valid context"); + let context = &mut *(ctx as *mut Context); + + let mut ctx = HandshakeContext::init(context); + let name = from_raw_parts(name, name_len); match cb(&mut ctx, name) { Ok(()) => 0, - Err(()) => -1, + Err(_) => -1, } } - unsafe { ssl_conf_sni(&mut self.inner, Some(sni_callback::), cb as *mut F as _) } - } + self.sni_callback = Some(Arc::new(cb)); + unsafe { ssl_conf_sni(self.into(), Some(sni_callback::), Arc::as_ptr(&mut self.sni_callback.as_ref().unwrap()) as *mut F as _) } + } + // The docs for mbedtls_x509_crt_verify say "The [callback] should return 0 for anything but a // fatal error.", so verify callbacks should return Ok(()) for anything but a fatal error. // Report verification errors by updating the flags in VerifyError. - pub fn set_verify_callback(&mut self, cb: &'c mut F) + #[cfg(feature = "threading")] + pub fn set_verify_callback(&mut self, cb: F) where - F: FnMut(&mut LinkedCertificate, i32, &mut VerifyError) -> Result<()>, + F: Fn(&Certificate, i32, &mut VerifyError) -> Result<()> + Send + Sync + 'static, { - unsafe extern "C" fn verify_callback( - closure: *mut c_void, - crt: *mut x509_crt, - depth: c_int, - flags: *mut u32, - ) -> c_int - where - F: FnMut(&mut LinkedCertificate, i32, &mut VerifyError) -> Result<()>, - { - let cb = &mut *(closure as *mut F); - let crt: &mut LinkedCertificate = - UnsafeFrom::from(crt).expect("valid certificate"); - let mut verify_error = match VerifyError::from_bits(*flags) { - Some(ve) => ve, - // This can only happen if mbedtls is setting flags in VerifyError that are - // missing from our definition. - None => return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA, - }; - let res = cb(crt, depth, &mut verify_error); - *flags = verify_error.bits(); - match res { - Ok(()) => 0, - Err(e) => e.to_int(), - } - } + self.verify_callback = Some(Arc::new(cb)); + unsafe { ssl_conf_verify(self.into(), Some(verify_callback::), Arc::as_ptr(&mut self.verify_callback.as_ref().unwrap()) as *mut F as _) } + } - unsafe { - ssl_conf_verify( - &mut self.inner, - Some(verify_callback::), - cb as *mut F as _, - ) - } + #[cfg(not(feature = "threading"))] + pub fn set_verify_callback(&mut self, cb: F) + where + F: Fn(&Certificate, i32, &mut VerifyError) -> Result<()> + 'static, + { + self.verify_callback = Some(Arc::new(cb)); + unsafe { ssl_conf_verify(self.into(), Some(verify_callback::), Arc::as_ptr(&mut self.verify_callback.as_ref().unwrap()) as *mut F as _) } } - pub fn set_ca_callback(&mut self, cb: &'c mut F) - where - F: FnMut(&LinkedCertificate, &mut ForeignOwnedCertListBuilder) -> Result<()>, + #[cfg(feature = "threading")] + pub fn set_ca_callback(&mut self, cb: F) + where + F: Fn(&Certificate, &mut ForeignOwnedCertListBuilder) -> Result<()> + Send + Sync + 'static, { - unsafe extern "C" fn ca_callback( - closure: *mut c_void, - child: *const x509_crt, - candidate_cas: *mut *mut x509_crt - ) -> c_int - where - F: FnMut(&LinkedCertificate, &mut ForeignOwnedCertListBuilder) -> Result<()>, - { - let cb = &mut *(closure as *mut F); - let child: &LinkedCertificate = UnsafeFrom::from(child).expect("valid child certificate"); - let mut cert_builder = ForeignOwnedCertListBuilder::new(); - match cb(child, &mut cert_builder) { - Ok(()) => { - *candidate_cas = cert_builder.to_x509_crt_ptr(); - 0 - }, - Err(e) => e.to_int(), - } - } + self.ca_callback = Some(Arc::new(cb)); + unsafe { ssl_conf_ca_cb( self.into(), Some(ca_callback::), Arc::as_ptr(&mut self.ca_callback.as_ref().unwrap()) as *mut F as _) } + } - unsafe { - ssl_conf_ca_cb( - &mut self.inner, - Some(ca_callback::), - cb as *mut F as _, - ) - } + #[cfg(not(feature = "threading"))] + pub fn set_ca_callback(&mut self, cb: F) + where + F: Fn(&Certificate, &mut ForeignOwnedCertListBuilder) -> Result<()> + 'static, + { + self.ca_callback = Some(Arc::new(cb)); + unsafe { ssl_conf_ca_cb( self.into(), Some(ca_callback::), Arc::as_ptr(&mut self.ca_callback.as_ref().unwrap()) as *mut F as _) } + } + + #[cfg(feature = "threading")] + pub fn set_dbg_callback(&mut self, cb: F) + where + F: (Fn(i32, &str, i32, &str) -> ()) + Send + Sync + 'static, + { + self.dbg_callback = Some(Arc::new(cb)); + unsafe { ssl_conf_dbg(self.into(), Some(dbg_callback::), Arc::as_ptr(&mut self.dbg_callback.as_ref().unwrap()) as *mut F as _) } + } + + #[cfg(not(feature = "threading"))] + pub fn set_dbg_callback(&mut self, cb: F) + where + F: (Fn(i32, &str, i32, &str) -> ()) + 'static, + { + self.dbg_callback = Some(Arc::new(cb)); + unsafe { ssl_conf_dbg(self.into(), Some(dbg_callback::), Arc::as_ptr(&mut self.dbg_callback.as_ref().unwrap()) as *mut F as _) } + } + +} + + +impl Drop for Config { + fn drop(&mut self) { + unsafe { ssl_config_free(self.into()); } } } /// Builds a linked list of x509_crt instances, all of which are owned by mbedtls. That is, the /// memory for these certificates has been allocated by mbedtls, on the C heap. This is needed for /// situations in which an mbedtls function takes ownership of a list of certs. The problem with -/// handing such functions a "normal" cert list such as certificate::LinkedCertificate or +/// handing such functions a "normal" cert list such as certificate::Certificate or /// certificate::List, is that those lists (at least partly) consist of memory allocated on the /// rust-side and hence cannot be freed on the c-side. pub struct ForeignOwnedCertListBuilder { @@ -354,10 +472,16 @@ impl ForeignOwnedCertListBuilder { } } - pub fn push_back(&mut self, cert: &LinkedCertificate) { + pub fn push_back(&mut self, cert: &Certificate) { self.try_push_back(cert.as_der()).expect("cert is a valid DER-encoded certificate"); } + pub fn try_push_back_pem(&mut self, cert: &[u8]) -> Result<()> { + // x509_crt_parse will allocate memory for the cert on the C heap + unsafe { x509_crt_parse(self.cert_list, cert.as_ptr(), cert.len()) }.into_result()?; + Ok(()) + } + pub fn try_push_back(&mut self, cert: &[u8]) -> Result<()> { // x509_crt_parse_der will allocate memory for the cert on the C heap unsafe { x509_crt_parse_der(self.cert_list, cert.as_ptr(), cert.len()) }.into_result()?; @@ -383,53 +507,88 @@ impl Drop for ForeignOwnedCertListBuilder { } } -setter_callback!(Config<'c>::set_rng(f: crate::rng::Random) = ssl_conf_rng); -setter_callback!(Config<'c>::set_dbg(f: DbgCallback) = ssl_conf_dbg); - -define!( - #[c_ty(ssl_key_cert)] - struct KeyCert; - impl<'a> UnsafeFrom {} -); +unsafe extern "C" fn verify_callback( + closure: *mut c_void, + crt: *mut x509_crt, + depth: c_int, + flags: *mut u32, +) -> c_int +where + F: Fn(&Certificate, i32, &mut VerifyError) -> Result<()> + 'static, +{ + if crt == ::core::ptr::null_mut() || closure == ::core::ptr::null_mut() || flags == ::core::ptr::null_mut() { + return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA; + } -pub struct KeyCertIter<'a> { - key_cert: Option<&'a KeyCert>, + let cb = &mut *(closure as *mut F); + let crt: &mut Certificate = UnsafeFrom::from(crt).expect("valid certificate"); + + let mut verify_error = match VerifyError::from_bits(*flags) { + Some(ve) => ve, + // This can only happen if mbedtls is setting flags in VerifyError that are + // missing from our definition. + None => return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA, + }; + + let res = cb(crt, depth, &mut verify_error); + *flags = verify_error.bits(); + match res { + Ok(()) => 0, + Err(e) => e.to_int(), + } } -impl<'a> Iterator for KeyCertIter<'a> { - type Item = (certificate::Iter<'a>, &'a Pk); - fn next(&mut self) -> Option { - self.key_cert.take().map(|key_cert| unsafe { - self.key_cert = UnsafeFrom::from(key_cert.inner.next as *const _); - ( - UnsafeFrom::from(key_cert.inner.cert as *const _).expect("not null"), - UnsafeFrom::from(key_cert.inner.key as *const _).expect("not null"), - ) - }) +unsafe extern "C" fn ca_callback( + closure: *mut c_void, + child: *const x509_crt, + candidate_cas: *mut *mut x509_crt +) -> c_int +where + F: Fn(&Certificate, &mut ForeignOwnedCertListBuilder) -> Result<()> + 'static, +{ + if child == ::core::ptr::null_mut() || closure == ::core::ptr::null_mut() || candidate_cas == ::core::ptr::null_mut() { + return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA; + } + + let cb = &mut *(closure as *mut F); + let crt: &Certificate = UnsafeFrom::from(child).expect("valid certificate"); + let mut cert_builder = ForeignOwnedCertListBuilder::new(); + match cb(&crt, &mut cert_builder) { + Ok(()) => { + *candidate_cas = cert_builder.to_x509_crt_ptr(); + 0 + }, + Err(e) => e.to_int(), } } -// TODO -// ssl_conf_export_keys_cb -// ssl_conf_dtls_cookies -// ssl_conf_dtls_anti_replay -// ssl_conf_dtls_badmac_limit -// ssl_conf_handshake_timeout -// ssl_conf_session_cache -// ssl_conf_psk -// ssl_conf_psk_cb -// ssl_conf_sig_hashes -// ssl_conf_alpn_protocols -// ssl_conf_fallback -// ssl_conf_encrypt_then_mac -// ssl_conf_extended_master_secret -// ssl_conf_arc4_support -// ssl_conf_max_frag_len -// ssl_conf_truncated_hmac -// ssl_conf_cbc_record_splitting -// ssl_conf_renegotiation -// ssl_conf_legacy_renegotiation -// ssl_conf_renegotiation_enforced -// ssl_conf_renegotiation_period -// +unsafe extern "C" fn dbg_callback( + closure: *mut c_void, + level: c_int, + file: *const c_char, + line: c_int, + message: *const c_char +) -> () +where + F: (Fn(i32, &str, i32, &str) -> ()) + 'static, +{ + if file == ::core::ptr::null_mut() || message == ::core::ptr::null_mut() { + return (); + } + + let cb = &mut *(closure as *mut F); + + let file = match std::ffi::CStr::from_ptr(file).to_str() { + Ok(text) => text, + Err(_) => return (), + }; + + let message = match std::ffi::CStr::from_ptr(message).to_str() { + Ok(text) => text, + Err(_) => return (), + }; + + + cb(level, file, line, message); +} diff --git a/mbedtls/src/ssl/context.rs b/mbedtls/src/ssl/context.rs index cbc17534a..7e9fdfc7c 100644 --- a/mbedtls/src/ssl/context.rs +++ b/mbedtls/src/ssl/context.rs @@ -6,42 +6,30 @@ * option. This file may not be copied, modified, or distributed except * according to those terms. */ -#[cfg(not(feature = "std"))] -use core_io::{self as io, Read, Write}; -#[cfg(feature = "std")] -use std::io::{self, Read, Write}; - use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void}; use mbedtls_sys::types::size_t; use mbedtls_sys::*; - -use crate::error::{Error, IntoResult, Result}; +use std::io::{Read, Write}; +use crate::error::{Error, Result, IntoResult}; +use std::sync::Arc; +use crate::ssl::config::{Config, Version, AuthMode}; use core::result::Result as StdResult; -use crate::private::UnsafeFrom; -use crate::ssl::config::{AuthMode, Config, Version}; -use crate::x509::{Crl, LinkedCertificate, VerifyError}; +use crate::x509::VerifyError; +use crate::pk::Pk; +use crate::x509::Crl; +use std::any::Any; +use crate::x509::certificate::MbedtlsList; +use crate::x509::Certificate; pub trait IoCallback { - unsafe extern "C" fn call_recv( - user_data: *mut c_void, - data: *mut c_uchar, - len: size_t, - ) -> c_int; - unsafe extern "C" fn call_send( - user_data: *mut c_void, - data: *const c_uchar, - len: size_t, - ) -> c_int; - + unsafe extern "C" fn call_recv(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int where Self: Sized; + unsafe extern "C" fn call_send(user_data: *mut c_void, data: *const c_uchar, len: size_t) -> c_int where Self: Sized; fn data_ptr(&mut self) -> *mut c_void; + fn as_any(&mut self) -> &mut dyn Any; } -impl IoCallback for IO { - unsafe extern "C" fn call_recv( - user_data: *mut c_void, - data: *mut c_uchar, - len: size_t, - ) -> c_int { +impl IoCallback for IO { + unsafe extern "C" fn call_recv(user_data: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int { let len = if len > (c_int::max_value() as size_t) { c_int::max_value() as size_t } else { @@ -53,11 +41,7 @@ impl IoCallback for IO { } } - unsafe extern "C" fn call_send( - user_data: *mut c_void, - data: *const c_uchar, - len: size_t, - ) -> c_int { + unsafe extern "C" fn call_send(user_data: *mut c_void, data: *const c_uchar, len: size_t) -> c_int { let len = if len > (c_int::max_value() as size_t) { c_int::max_value() as size_t } else { @@ -72,65 +56,109 @@ impl IoCallback for IO { fn data_ptr(&mut self) -> *mut c_void { self as *mut IO as *mut _ } + + fn as_any(&mut self) -> &mut dyn Any { + self + } } -define!( - #[c_ty(ssl_context)] - struct Context<'config>; - const init: fn() -> Self = ssl_init; - const drop: fn(&mut Self) = ssl_free; - impl<'a> Into {} - impl<'a> UnsafeFrom {} -); - -pub struct Session<'ctx> { - inner: &'ctx mut ssl_context, +// We need repr(C) because we need to cast from ssl_context and back +#[repr(C)] +pub struct Context { + // This needs to always be first (and class of type repr(C)) so that casting to and from Context works. + inner: ssl_context, + + // config is used read-only for mutliple contexts and is immutable once configured. + #[allow(dead_code)] + config: Option>, + + // Must be held in heap and pointer to it as pointer is sent to MbedSSL and can't be re-allocated. + #[allow(dead_code)] + io: Option>, + + handshake_ca_cert: Option>>, + handshake_crl: Option>, + + handshake_cert: Vec>>, + handshake_pk: Vec>, } -#[cfg(feature = "threading")] -unsafe impl<'ctx> Send for Session<'ctx> {} +impl Into<*mut mbedtls_sys::ssl_context> for &mut Context { + fn into(self) -> *mut mbedtls_sys::ssl_context { + &mut self.inner + } +} -pub struct HandshakeContext<'ctx> { - inner: &'ctx mut ssl_context, +impl Into<*const mbedtls_sys::ssl_context> for &Context { + fn into(self) -> *const mbedtls_sys::ssl_context { + &self.inner + } } -impl<'config> Context<'config> { - pub fn new(config: &'config Config) -> Result> { - let mut ret = Self::init(); - unsafe { ssl_setup(&mut ret.inner, config.into()) } - .into_result() - .map(|_| ret) + +#[allow(dead_code)] +impl Context { + pub fn new(config: Arc) -> Self { + let mut inner = ssl_context::default(); + + unsafe { + ssl_init(&mut inner); + ssl_setup(&mut inner, (&*config).into()); + }; + + Context { + inner, + config: Some(config.clone()), + io: None, + + handshake_ca_cert: None, + handshake_crl: None, + + handshake_cert: vec![], + handshake_pk: vec![], + } } - pub fn establish<'c, F: IoCallback>( - &'c mut self, - io: &'c mut F, - hostname: Option<&str>, - ) -> Result> { + pub fn establish(&mut self, io: T, hostname: Option<&str>) -> Result<()> { + self.handshake_cert.clear(); + self.handshake_pk.clear(); + self.handshake_ca_cert = None; + self.handshake_crl = None; + unsafe { - ssl_session_reset(&mut self.inner).into_result()?; + let mut io = Box::new(io); + + ssl_session_reset(self.into()).into_result()?; self.set_hostname(hostname)?; + let ptr = &mut *io as *mut _ as *mut c_void; ssl_set_bio( - &mut self.inner, - io.data_ptr(), - Some(F::call_send), - Some(F::call_recv), + self.into(), + ptr, + Some(T::call_send), + Some(T::call_recv), None, ); - match ssl_handshake(&mut self.inner).into_result() { + + self.io = Some(io); + + match ssl_handshake(self.into()).into_result() { Err(e) => { // safely end borrow of io - ssl_set_bio(&mut self.inner, ::core::ptr::null_mut(), None, None, None); + ssl_set_bio(self.into(), ::core::ptr::null_mut(), None, None, None); + self.io = None; Err(e) + }, + Ok(_) => { + Ok(()) } - Ok(_) => Ok(Session { - inner: &mut self.inner, - }), } } } +} +impl Context { + #[allow(dead_code)] #[cfg(not(feature = "std"))] fn set_hostname(&mut self, hostname: Option<&str>) -> Result<()> { match hostname { @@ -139,16 +167,13 @@ impl<'config> Context<'config> { } } + #[allow(dead_code)] #[cfg(feature = "std")] fn set_hostname(&mut self, hostname: Option<&str>) -> Result<()> { - if self.inner.hostname != ::core::ptr::null_mut() { - // potential MEMORY LEAK! See https://github.com/ARMmbed/mbedtls/issues/836 - self.inner.hostname = ::core::ptr::null_mut(); - } if let Some(s) = hostname { let cstr = ::std::ffi::CString::new(s).map_err(|_| Error::SslBadInputData)?; unsafe { - ssl_set_hostname(&mut self.inner, cstr.as_ptr()) + ssl_set_hostname(self.into(), cstr.as_ptr()) .into_result() .map(|_| ()) } @@ -158,70 +183,37 @@ impl<'config> Context<'config> { } pub fn verify_result(&self) -> StdResult<(), VerifyError> { - match unsafe { ssl_get_verify_result(&self.inner) } { + match unsafe { ssl_get_verify_result(self.into()) } { 0 => Ok(()), flags => Err(VerifyError::from_bits_truncate(flags)), } } - pub fn config(&self) -> &'config Config { - unsafe { UnsafeFrom::from(self.inner.conf).expect("not null") } + pub fn config(&self) -> &Option> { + &self.config } -} - -impl<'ctx> HandshakeContext<'ctx> { - pub fn set_authmode(&mut self, am: AuthMode) { - unsafe { ssl_set_hs_authmode(self.inner, am.into()) } - } - - pub fn set_ca_list>( - &mut self, - list: Option, - crl: Option<&'ctx mut Crl>, - ) { + + #[allow(dead_code)] + pub fn close(&mut self) { unsafe { - ssl_set_hs_ca_chain( - self.inner, - list.map(Into::into) - .map(Into::into) - .unwrap_or(::core::ptr::null_mut()), - crl.map(Into::into).unwrap_or(::core::ptr::null_mut()), - ) + ssl_close_notify(self.into()); + ssl_set_bio(self.into(), ::core::ptr::null_mut(), None, None, None); + self.io = None; } } - /// If this is never called, will use the set of private keys and - /// certificates configured in the `Config` associated with this `Context`. - /// If this is called at least once, all those are ignored and the set - /// specified using this function is used. - pub fn push_cert>( - &mut self, - chain: C, - key: &'ctx mut crate::pk::Pk, - ) -> Result<()> { - unsafe { - ssl_set_hs_own_cert(self.inner, chain.into().into(), key.into()) - .into_result() - .map(|_| ()) + pub fn get_mut_io(&mut self) -> std::io::Result<&mut T> { + match self.io.as_mut() { + Some(stream) => { + match stream.as_any().downcast_mut::() { + Some(s) => Ok(s), + None => Err(std::io::Error::new(std::io::ErrorKind::NotFound, "Peer kind is not expected")), + } + } + None => Err(std::io::Error::new(std::io::ErrorKind::NotFound, "No peer available")), } } -} - -impl<'ctx> ::core::ops::Deref for HandshakeContext<'ctx> { - type Target = Context<'ctx>; - - fn deref(&self) -> &Context<'ctx> { - unsafe { UnsafeFrom::from(&*self.inner as *const _).expect("not null") } - } -} - -impl<'ctx> UnsafeFrom<*mut ssl_context> for HandshakeContext<'ctx> { - unsafe fn from(ctx: *mut ssl_context) -> Option> { - ctx.as_mut().map(|ctx| HandshakeContext { inner: ctx }) - } -} - -impl<'a> Session<'a> { + /// Return the minor number of the negotiated TLS version pub fn minor_version(&self) -> i32 { self.inner.minor_ver @@ -235,7 +227,7 @@ impl<'a> Session<'a> { /// Return the number of bytes currently available to read that /// are stored in the Session's internal read buffer pub fn bytes_available(&self) -> usize { - unsafe { ssl_get_bytes_avail(self.inner) } + unsafe { ssl_get_bytes_avail(self.into()) } } pub fn version(&self) -> Version { @@ -251,32 +243,49 @@ impl<'a> Session<'a> { } } + + // Session specific functions + /// Return the 16-bit ciphersuite identifier. /// All assigned ciphersuites are listed by the IANA in /// https://www.iana.org/assignments/tls-parameters/tls-parameters.txt - pub fn ciphersuite(&self) -> u16 { + pub fn ciphersuite(&self) -> Result { if self.inner.session == ::core::ptr::null_mut() { - 0 - } else { - unsafe { self.inner.session.as_ref().unwrap().ciphersuite as u16 } + return Err(Error::SslBadInputData); } + + Ok(unsafe { self.inner.session.as_ref().unwrap().ciphersuite as u16 }) } - pub fn peer_cert(&self) -> Option { - unsafe { UnsafeFrom::from(ssl_get_peer_cert(self.inner)) } + // This makes a copy of the certificate as peer_cert may be destroyed outside our control. + pub fn peer_cert(&self) -> Result>> { + unsafe { + // ssl_get_peer_cert checks for NULL unlike other functions. + let peer_cert = ssl_get_peer_cert(self.into()); + + if peer_cert as *const _ == ::core::ptr::null() { + return Err(Error::SslBadInputData); + } + + let cert = MbedtlsList::::from_cert(&*peer_cert); + Ok(Some(cert)) + } } +} - pub fn verify_result(&self) -> StdResult<(), VerifyError> { - match unsafe { ssl_get_verify_result(self.inner) } { - 0 => Ok(()), - flags => Err(VerifyError::from_bits_truncate(flags)), +impl Drop for Context { + fn drop(&mut self) { + unsafe { + ssl_close_notify(self.into()); + ssl_set_bio(self.into(), ::core::ptr::null_mut(), None, None, None); + ssl_free(self.into()); } } } -impl<'a> Read for Session<'a> { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - match unsafe { ssl_read(self.inner, buf.as_mut_ptr(), buf.len()).into_result() } { +impl Read for Context { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + match unsafe { ssl_read(self.into(), buf.as_mut_ptr(), buf.len()).into_result() } { Err(Error::SslPeerCloseNotify) => Ok(0), Err(e) => Err(crate::private::error_to_io_error(e)), Ok(i) => Ok(i as usize), @@ -284,29 +293,105 @@ impl<'a> Read for Session<'a> { } } -impl<'a> Write for Session<'a> { - fn write(&mut self, buf: &[u8]) -> io::Result { - match unsafe { ssl_write(self.inner, buf.as_ptr(), buf.len()).into_result() } { +impl Write for Context { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + match unsafe { ssl_write(self.into(), buf.as_ptr(), buf.len()).into_result() } { Err(Error::SslPeerCloseNotify) => Ok(0), Err(e) => Err(crate::private::error_to_io_error(e)), Ok(i) => Ok(i as usize), } } - fn flush(&mut self) -> io::Result<()> { + fn flush(&mut self) -> std::io::Result<()> { Ok(()) } } -impl<'a> Drop for Session<'a> { - fn drop(&mut self) { + +pub struct HandshakeContext<'ctx> { + pub context: &'ctx mut Context, +} + +/// +/// Class exists only during SNI callback that is configured from Config. +/// SNI Callback must provide input whos lifetime exceed the SNI closure to avoid memory corruptions. +/// That can be achieved easily by storing certificate chains/crls inside the closure for the lifetime of the closure. +/// +/// That is due to SNI being held by an Arc inside Config. +/// Config lives longer then Context. Context lives longer then Handshake. +/// +/// Alternatives are not possible due to: +/// - mbedtls not providing any callbacks on handshake finish. +/// - no reasonable way to obtain a storage within the sni callback tied to the handshake or to the rust Context. (without resorting to a unscalable map or pointer magic that mbedtls may invalidate) +/// +impl<'ctx> HandshakeContext<'ctx> { + + pub fn init(context: &'ctx mut Context) -> Self { + HandshakeContext { context } + } + + pub fn set_authmode(&mut self, am: AuthMode) -> Result<()> { + if self.context.inner.handshake as *const _ == ::core::ptr::null() { + return Err(Error::SslBadInputData); + } + + unsafe { ssl_set_hs_authmode(self.context.into(), am as i32) } + Ok(()) + } + + /// @warning: chain/crl must live the same as the SNI callback otherwise risk of dangling pointers. + pub fn set_ca_list( + &mut self, + chain: Arc>, + crl: Option>, + ) -> Result<()> { + // mbedtls_ssl_set_hs_ca_chain does not check for NULL handshake. + if self.context.inner.handshake as *const _ == ::core::ptr::null() { + return Err(Error::SslBadInputData); + } + + // This will override current handshake CA chain. + unsafe { + ssl_set_hs_ca_chain( + self.context.into(), + (&**chain).into(), + crl.as_ref().map(|crl| (&(**crl)).into()).unwrap_or(::core::ptr::null_mut()), + ); + } + + self.context.handshake_ca_cert = Some(chain); + self.context.handshake_crl = crl; + Ok(()) + } + + /// If this is never called, will use the set of private keys and + /// certificates configured in the `Config` associated with this `Context`. + /// If this is called at least once, all those are ignored and the set + /// specified using this function is used. + /// + /// @warning: chain/key must live the same as the SNI callback otherwise risk of dangling pointers. + pub fn push_cert( + &mut self, + chain: Arc>, + key: Arc, + ) -> Result<()> { + // mbedtls_ssl_set_hs_own_cert does not check for NULL handshake. + if self.context.inner.handshake as *const _ == ::core::ptr::null() { + return Err(Error::SslBadInputData); + } + + // This will append provided certificate pointers in internal structures. unsafe { - ssl_close_notify(self.inner); - ssl_set_bio(self.inner, ::core::ptr::null_mut(), None, None, None); + ssl_set_hs_own_cert(self.context.into(), (&**chain).into(), (&*key).into()).into_result()?; } + self.context.handshake_cert.push(chain); + self.context.handshake_pk.push(key); + + Ok(()) } } + // ssl_get_alpn_protocol // ssl_get_max_frag_len // ssl_get_record_expansion diff --git a/mbedtls/src/ssl/mod.rs b/mbedtls/src/ssl/mod.rs index ea79153b1..430d439ea 100644 --- a/mbedtls/src/ssl/mod.rs +++ b/mbedtls/src/ssl/mod.rs @@ -14,8 +14,8 @@ pub mod ticket; #[doc(inline)] pub use self::ciphersuites::CipherSuite; #[doc(inline)] -pub use self::config::{Config, Version}; +pub use self::config::{Config, Version, UseSessionTickets}; #[doc(inline)] -pub use self::context::{Context, HandshakeContext, Session}; +pub use self::context::Context; #[doc(inline)] pub use self::ticket::TicketContext; diff --git a/mbedtls/src/ssl/ticket.rs b/mbedtls/src/ssl/ticket.rs index 77ce26777..54bec3bc8 100644 --- a/mbedtls/src/ssl/ticket.rs +++ b/mbedtls/src/ssl/ticket.rs @@ -11,6 +11,8 @@ use crate::error::{IntoResult, Result}; use mbedtls_sys::types::raw_types::{c_int, c_uchar, c_void}; use mbedtls_sys::types::size_t; use mbedtls_sys::*; +use std::sync::Arc; +use crate::rng::RngCallback; pub trait TicketCallback { unsafe extern "C" fn call_write( @@ -20,46 +22,69 @@ pub trait TicketCallback { end: *const c_uchar, tlen: *mut size_t, lifetime: *mut u32, - ) -> c_int; + ) -> c_int where Self: Sized; unsafe extern "C" fn call_parse( p_ticket: *mut c_void, session: *mut ssl_session, buf: *mut c_uchar, len: size_t, - ) -> c_int; + ) -> c_int where Self: Sized; - fn data_ptr(&mut self) -> *mut c_void; + fn data_ptr(&self) -> *mut c_void; } -define!( - #[c_ty(ssl_ticket_context)] - struct TicketContext<'rng>; - const init: fn() -> Self = ssl_ticket_init; - const drop: fn(&mut Self) = ssl_ticket_free; -); +pub struct TicketContext { + inner: Box, -impl<'rng> TicketContext<'rng> { - pub fn new( - rng: &'rng mut F, + // We set rng from constructur, we never read it directly. It is only used to ensure rng lives as long as we need. + #[allow(dead_code)] + rng: Arc, +} + +#[cfg(feature = "threading")] +unsafe impl Sync for TicketContext {} + +#[cfg(feature = "threading")] +unsafe impl Send for TicketContext {} + + +impl Drop for TicketContext { + fn drop(&mut self) { + unsafe { ssl_ticket_free(self.into()); } + } +} + +impl Into<*mut mbedtls_sys::ssl_ticket_context> for &mut TicketContext { + fn into(self) -> *mut mbedtls_sys::ssl_ticket_context { + &mut *self.inner + } +} + +impl TicketContext { + pub fn new( + rng: Arc, cipher: CipherType, lifetime: u32, - ) -> Result> { - let mut ret = Self::init(); + ) -> Result { + + let mut inner = Box::new(ssl_ticket_context::default()); + unsafe { + ssl_ticket_init(&mut *inner); ssl_ticket_setup( - &mut ret.inner, - Some(F::call), + &mut *inner, + Some(T::call), rng.data_ptr(), cipher.into(), lifetime, - ) + ).into_result()?; } - .into_result() - .map(|_| ret) + + Ok(TicketContext { inner, rng }) } } -impl<'rng> TicketCallback for TicketContext<'rng> { +impl TicketCallback for TicketContext { unsafe extern "C" fn call_write( p_ticket: *mut c_void, session: *const ssl_session, @@ -80,7 +105,7 @@ impl<'rng> TicketCallback for TicketContext<'rng> { ssl_ticket_parse(p_ticket, session, buf, len) } - fn data_ptr(&mut self) -> *mut c_void { - &mut self.inner as *mut _ as *mut _ + fn data_ptr(&self) -> *mut c_void { + &*self.inner as *const _ as *mut _ } } diff --git a/mbedtls/src/wrapper_macros.rs b/mbedtls/src/wrapper_macros.rs index dba58ea33..e4e06e817 100644 --- a/mbedtls/src/wrapper_macros.rs +++ b/mbedtls/src/wrapper_macros.rs @@ -15,45 +15,82 @@ macro_rules! as_item { macro_rules! callback { //{ ($($arg:ident: $ty:ty),*) -> $ret:ty } => { //}; - { $n:ident$( : $sync:ident )*($($arg:ident: $ty:ty),*) -> $ret:ty } => { + { $n:ident, $m:ident$( : $sync:ident )*($($arg:ident: $ty:ty),*) -> $ret:ty } => { #[cfg(not(feature="threading"))] pub trait $n { - unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret; + unsafe extern "C" fn call_mut(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized; - fn data_ptr(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void; + fn data_ptr_mut(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void; } #[cfg(feature="threading")] pub trait $n $( : $sync )* { - unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret; + unsafe extern "C" fn call_mut(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized; - fn data_ptr(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void; + fn data_ptr_mut(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void; } #[cfg(not(feature="threading"))] impl $n for F where F: FnMut($($ty),*) -> $ret { - unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret { + unsafe extern "C" fn call_mut(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized { (&mut*(user_data as *mut F))($($arg),*) } - fn data_ptr(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void { + fn data_ptr_mut(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void { self as *mut F as *mut _ } } #[cfg(feature="threading")] impl $n for F where F: Sync + FnMut($($ty),*) -> $ret { - unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret { + unsafe extern "C" fn call_mut(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized { (&mut*(user_data as *mut F))($($arg),*) } - fn data_ptr(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void { - self as *mut F as *mut _ + fn data_ptr_mut(&mut self) -> *mut ::mbedtls_sys::types::raw_types::c_void { + self as *const F as *mut _ + } + } + + #[cfg(not(feature="threading"))] + pub trait $m { + unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized; + + fn data_ptr(&self) -> *mut ::mbedtls_sys::types::raw_types::c_void; + } + + #[cfg(feature="threading")] + pub trait $m $( : $sync )* { + unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized; + + fn data_ptr(&self) -> *mut ::mbedtls_sys::types::raw_types::c_void; + } + + #[cfg(not(feature="threading"))] + impl $m for F where F: $n + Fn($($ty),*) -> $ret { + unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized { + (&mut*(user_data as *mut F))($($arg),*) + } + + fn data_ptr(&self) -> *mut ::mbedtls_sys::types::raw_types::c_void { + self as *const F as *mut F as *mut _ + } + } + + #[cfg(feature="threading")] + impl $m for F where F: $n + Sync + Fn($($ty),*) -> $ret { + unsafe extern "C" fn call(user_data: *mut ::mbedtls_sys::types::raw_types::c_void, $($arg:$ty),*) -> $ret where Self: Sized { + (&mut*(user_data as *mut F))($($arg),*) + } + + fn data_ptr(&self) -> *mut ::mbedtls_sys::types::raw_types::c_void { + self as *const F as *mut _ } } }; } +// TODO: simplify and reuse where possible macro_rules! define { { #[c_ty($inner:ident)] $(#[$m:meta])* struct $name:ident$(<$l:tt>)*; $($defs:tt)* } => { define_struct!(define $(#[$m])* struct $name $(lifetime $l)* inner $inner); @@ -226,44 +263,4 @@ macro_rules! define_struct { { lifetime $l:tt } => {}; } -macro_rules! setter { - { $(#[$m:meta])* $rfn:ident($n:ident : $rty:ty) = $cfn:ident } => { - $(#[$m])* - pub fn $rfn(&mut self, $n: $rty) { - unsafe{::mbedtls_sys::$cfn(&mut self.inner,$n.into())} - } - } -} - -// can't make this work without as as_XXX! macro, and there is no as_method!... -macro_rules! setter_callback { - { $(#[$m:meta])* $s:ident<$l:tt>::$rfn:ident($n:ident : $($rty:tt)+) = $cfn:ident } => { - as_item!( - impl<$l> $s<$l> { - $(#[$m])* - pub fn $rfn(&mut self, $n: Option<&$l mut F>) { - unsafe{::mbedtls_sys::$cfn( - &mut self.inner, - $n.as_ref().map(|_|F::call as _), - $n.map(|f|f.data_ptr()).unwrap_or(::core::ptr::null_mut()) - )} - } - } - ); - } -} - -macro_rules! getter { - { $(#[$m:meta])* $rfn:ident() -> $rty:ty = .$cfield:ident } => { - $(#[$m])* - pub fn $rfn(&self) -> $rty { - self.inner.$cfield.into() - } - }; - { $(#[$m:meta])* $rfn:ident() -> $rty:ty = fn $cfn:ident } => { - $(#[$m])* - pub fn $rfn(&self) -> $rty { - unsafe{::mbedtls_sys::$cfn(&self.inner).into()} - } - }; -} +// TODO: Bring back getter/setter macros \ No newline at end of file diff --git a/mbedtls/src/x509/certificate.rs b/mbedtls/src/x509/certificate.rs index 65506557f..e0e168667 100644 --- a/mbedtls/src/x509/certificate.rs +++ b/mbedtls/src/x509/certificate.rs @@ -7,24 +7,27 @@ * according to those terms. */ use core::fmt; -use core::marker::PhantomData; -use core::ops::{Deref, DerefMut}; -use core::ptr; #[cfg(not(feature = "std"))] use crate::alloc_prelude::*; use mbedtls_sys::types::raw_types::c_char; use mbedtls_sys::*; +use crate::x509::Time; #[cfg(feature = "std")] use yasna::{BERDecodable, BERReader, ASN1Result, ASN1Error, ASN1ErrorKind, models::ObjectIdentifier}; - -use crate::pk::Pk; use crate::error::{Error, IntoResult, Result}; -use crate::private::UnsafeFrom; -use crate::rng::Random; use crate::hash::Type as MdType; +use crate::pk::Pk; +use crate::rng::Random; +use crate::private::UnsafeFrom; +use crate::{forward_mbedtls_calloc, forward_mbedtls_free}; +use core::ops::{Deref, DerefMut}; +use core::ptr::NonNull; +use mbedtls_sys::types::raw_types::c_void; +use core::ptr::drop_in_place; +use core::marker::PhantomData; #[derive(Debug,Copy,Clone,Eq,PartialEq)] pub enum CertificateVersion { @@ -33,12 +36,10 @@ pub enum CertificateVersion { V3 } -define!( - #[c_ty(x509_crt)] - struct Certificate; - const init: fn() -> Self = x509_crt_init; - const drop: fn(&mut Self) = x509_crt_free; -); +#[repr(C)] +pub struct MbedtlsList { + inner: NonNull +} #[cfg(feature = "std")] #[derive(Debug, Clone, Eq, PartialEq)] @@ -60,88 +61,127 @@ impl BERDecodable for Extension { } } -impl Certificate { - pub fn from_der(der: &[u8]) -> Result { - let mut ret = Self::init(); - unsafe { x509_crt_parse_der(&mut ret.inner, der.as_ptr(), der.len()) }.into_result()?; - Ok(ret) - } +//TODO: Provide MbedtlsBox as well for single certificate storage - /// Input must be NULL-terminated - pub fn from_pem(pem: &[u8]) -> Result { - let mut ret = Self::init(); - unsafe { x509_crt_parse(&mut ret.inner, pem.as_ptr(), pem.len()) }.into_result()?; - let mut fake = Self::init(); - ::core::mem::swap(&mut fake.inner.next, &mut ret.inner.next); - Ok(ret) - } +#[cfg(feature = "threading")] +unsafe impl<> Send for MbedtlsList {} - /// Input must be NULL-terminated - #[cfg(buggy)] - pub fn from_pem_multiple(pem: &[u8]) -> Result> { - let mut vec; +#[cfg(feature = "threading")] +unsafe impl<> Sync for MbedtlsList {} + +impl<> MbedtlsList { + fn new() -> Result { unsafe { - // first, find out how many certificates we're parsing - let mut dummy = Certificate::init(); - x509_crt_parse(&mut dummy.inner, pem.as_ptr(), pem.len()).into_result()?; + let inner = forward_mbedtls_calloc(1, core::mem::size_of::()) as *mut x509_crt; + if inner == core::ptr::null_mut() { + return Err(Error::SslAllocFailed); + } + + x509_crt_init(inner); + Ok(Self { inner: NonNull::new_unchecked(inner as *mut Certificate) }) + } + } - // then allocate enough certs with our allocator - vec = Vec::new(); - let mut cur: *mut _ = &mut dummy.inner; + pub fn from_der(der: &[u8]) -> Result { + let mut cert = Self::new()?; + cert.push_back_der(der)?; + Ok(cert) + } + + pub fn from_pem(pem_or_der: &[u8]) -> Result { + let mut cert = Self::new()?; + cert.push_back(pem_or_der)?; + Ok(cert) + } + + pub fn from_cert(source: &x509_crt) -> Self { + unsafe { + let der = std::slice::from_raw_parts(source.raw.p, source.raw.len); + let mut cert = Self::from_der(&der).expect("Failed re-parsing existing DER"); + + let mut cur = source.next; while cur != ::core::ptr::null_mut() { - vec.push(Certificate::init()); + let der = std::slice::from_raw_parts((*cur).raw.p, (*cur).raw.len); + cert.push_back_der(&der).expect("Failed re-parsing existing DER"); cur = (*cur).next; } + + cert + } + } - // link them together, they will become unlinked again when List drops - let list = List::from_vec(&mut vec).unwrap(); + pub fn push_back_der(&mut self, der: &[u8]) -> Result<()> { + unsafe { x509_crt_parse_der(self.inner.as_ref().into(), der.as_ptr(), der.len()) }.into_result()?; + Ok(()) + } + + pub fn push_back(&mut self, pem_or_der: &[u8]) -> Result<()> { + unsafe { x509_crt_parse(self.inner.as_ref().into(), pem_or_der.as_ptr(), pem_or_der.len()) }.into_result()?; + Ok(()) + } - // load the data again but into our allocated list - x509_crt_parse(&mut list.head.inner, pem.as_ptr(), pem.len()).into_result()?; - }; - Ok(vec) + pub fn push_back_list(&mut self, other: MbedtlsList::) { + unsafe { + let mut i : *mut x509_crt = self.inner.as_ref().into(); + while (*i).next != ::core::ptr::null_mut() { + i = (*i).next; + } + (*i).next = other.inner.as_ref().into(); + core::mem::forget(other); + } + } + + pub fn iter(&self) -> Iter<'_> { + unsafe { + Iter { + next: self.inner.as_ref().into(), + r: PhantomData, + } + } } } -impl fmt::Debug for Certificate { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match crate::private::alloc_string_repeat(|buf, size| unsafe { - x509_crt_info(buf, size, b"\0".as_ptr() as *const _, &self.inner) - }) { - Err(_) => Err(fmt::Error), - Ok(s) => f.write_str(&s), +impl Drop for MbedtlsList { + fn drop(&mut self) { + unsafe { + drop_in_place(self.inner.as_ptr()); + forward_mbedtls_free(self.inner.as_ptr() as *mut c_void) } } } -impl Clone for Certificate { - fn clone(&self) -> Certificate { - let mut ret = Self::init(); +impl<> Clone for MbedtlsList { + fn clone(&self) -> MbedtlsList { unsafe { - x509_crt_parse_der(&mut ret.inner, self.inner.raw.p, self.inner.raw.len) - .into_result() - .unwrap() - }; - ret + Self::from_cert(&self.inner.as_ref().inner) + } } } -impl Deref for Certificate { - type Target = LinkedCertificate; - fn deref(&self) -> &LinkedCertificate { - unsafe { UnsafeFrom::from(&self.inner as *const _).unwrap() } +impl Deref for MbedtlsList { + type Target = T; + fn deref(&self) -> &T { + unsafe { self.inner.as_ref() } } } -impl DerefMut for Certificate { - fn deref_mut(&mut self) -> &mut LinkedCertificate { - unsafe { UnsafeFrom::from(&mut self.inner as *mut _).unwrap() } +impl DerefMut for MbedtlsList { + fn deref_mut(&mut self) -> &mut T { + unsafe { self.inner.as_mut() } } } #[repr(C)] -pub struct LinkedCertificate { - inner: x509_crt, +pub struct Certificate { + pub inner: x509_crt +} + +impl Drop for Certificate { + fn drop(&mut self) { + unsafe { + x509_crt_free(self.into()); + } + } } fn x509_buf_to_vec(buf: &x509_buf) -> Vec { @@ -153,16 +193,17 @@ fn x509_buf_to_vec(buf: &x509_buf) -> Vec { slice.to_owned() } -fn x509_time_to_time(tm: &x509_time) -> Result { +fn x509_time_to_time(tm: &x509_time) -> Result