[
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CI\n\non:\n  pull_request:\n  push:\n    branches: main\n\nenv:\n  RUST_BACKTRACE: 1\n  CARGO_PROFILE_DEV_DEBUG: 0\n\njobs:\n  test:\n    name: Tests\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ macos-latest ]\n        rust: [ 1.85.0, stable, nightly ]\n\n    steps:\n      - name: Checkout sources\n        uses: actions/checkout@v2\n\n      - name: Install stable toolchain\n        uses: dtolnay/rust-toolchain@v1\n        with:\n          toolchain: ${{ matrix.rust }}\n\n      - uses: actions/cache/restore@v5\n        name: Cache crates.io\n        with:\n          path: |\n            ~/.cargo/registry/index\n            ~/.cargo/registry/cache\n          key: cratesio-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}\n\n      - name: Fix time MSRV\n        run: |\n          cargo update -p time --precise 0.3.41\n          cargo update -p time-core --precise 0.1.4\n\n      - uses: actions/cache@v5\n        name: Cache build dir\n        with:\n          path: target\n          key: tests-${{ runner.os }}-${{ matrix.rust }}-${{ hashFiles('Cargo.lock') }}\n\n      - name: Check default features\n        run: cargo check --all\n\n      - name: Run cargo test\n        run: cargo test --all-features --all\n\n  lints:\n    name: Lints and Breaking Changes\n    runs-on: macos-latest\n    continue-on-error: true\n    steps:\n      - name: Checkout sources\n        uses: actions/checkout@v2\n\n      - name: Install stable toolchain\n        uses: dtolnay/rust-toolchain@v1\n        with:\n          toolchain: stable\n          components: clippy, rustfmt\n\n      - uses: actions/cache@v5\n        name: Cache crates.io\n        with:\n          path: |\n            ~/.cargo/registry/index\n            ~/.cargo/registry/cache\n          key: cratesio-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}\n\n      - name: DO NOT USE RUSTFMT\n        run: \"if cargo fmt --quiet --check -- --config-path=/dev/null; then echo >&2 'Do not reformat the code with rustfmt. This project does not use rustfmt.'; fi\"\n\n      - run: cargo generate-lockfile\n\n      - uses: actions/cache@v5\n        name: Cache build dir\n        with:\n          path: target\n          key: lints-${{ runner.os }}-${{ matrix.rust }}-${{ hashFiles('Cargo.lock') }}\n\n      - name: SemVer check\n        uses: obi1kenobi/cargo-semver-checks-action@v2\n\n      - name: Run cargo clippy\n        run: cargo clippy --all-features\n\n  ios:\n    name: iOS and Intel compile-check\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout sources\n        uses: actions/checkout@v2\n\n      - name: Install stable toolchain\n        uses: dtolnay/rust-toolchain@v1\n        with:\n          toolchain: stable\n          target: aarch64-apple-ios,x86_64-apple-darwin\n\n      - uses: actions/cache/restore@v5\n        name: Cache crates.io\n        with:\n          path: |\n            ~/.cargo/registry/index\n            ~/.cargo/registry/cache\n          key: cratesio-${{ runner.os }}-${{ hashFiles('Cargo.toml') }}\n\n      - run: cargo generate-lockfile\n\n      - uses: actions/cache@v5\n        name: Cache build dir\n        with:\n          path: target\n          key: lints-${{ runner.os }}-${{ matrix.rust }}-${{ hashFiles('Cargo.lock') }}\n\n      - name: Run check iOS\n        run: cargo check --all-features -p security-framework --target aarch64-apple-ios\n\n      - name: Run check Intel\n        run: cargo check --all-features -p security-framework --target x86_64-apple-darwin\n"
  },
  {
    "path": ".gitignore",
    "content": "target/\nCargo.lock\n.cargo/\n.DS_Store\n.idea\n*.iml\n.vscode\n"
  },
  {
    "path": ".rustfmt.toml",
    "content": "# please do not use rustfmt, it destroys well-formatted code\ndisable_all_formatting = true\nignore = [\"/\"]\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n    \"security-framework-sys\",\n    \"security-framework\",\n    \"iostest\",\n    \"systest\"\n]\n\n[workspace.lints.clippy]\npedantic = { level = \"warn\", priority = -100 }\ncast_possible_truncation = \"allow\"\ncast_possible_wrap = \"allow\"\ncast_sign_loss = \"allow\"\nif_not_else = \"allow\"\ninline_always = \"allow\"\nitems_after_statements = \"allow\"\niter_not_returning_iterator = \"allow\"\nmap_unwrap_or = \"allow\"\nmissing_errors_doc = \"allow\"\nmissing_panics_doc = \"allow\"\nmodule_name_repetitions = \"allow\"\nredundant_closure_for_method_calls = \"allow\"\nsimilar_names = \"allow\"\nunnested_or_patterns = \"allow\"\nwildcard_imports = \"allow\"\ndoc_markdown = \"allow\"\ndefault_trait_access = \"allow\"\nneedless_pass_by_value = \"allow\"\nneedless_continue = \"allow\"\nstruct_field_names = \"allow\"\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Steven Fackler\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# macOS/iOS Security framework for Rust\n\n[![Latest Version](https://img.shields.io/crates/v/security-framework.svg)](https://lib.rs/crates/security-framework)\n\n[Documentation](https://docs.rs/security-framework)\n\nBindings to the Apple's `Security.framework`. Allows use of TLS and Keychain from Rust.\n\n## License\n\nLicensed under either of\n * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you shall be dual licensed as above, without any\nadditional terms or conditions.\n\n"
  },
  {
    "path": "iostest/Cargo.toml",
    "content": "[package]\nname = \"iostest\"\nversion = \"0.1.0\"\nedition = \"2021\"\npublish = false\n\n[lib]\ncrate-type = [\"staticlib\"]\n\n[dependencies]\ncore-foundation = \"0.10.0\"\nsecurity-framework = { path = \"../security-framework\" }\nsecurity-framework-sys = { path = \"../security-framework-sys\" }\n\n[dev-dependencies]\nrand = \"0.8.5\"\nserial_test = \"3.3\"\n\n[package.metadata.release]\nrelease = false\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harness/Assets.xcassets/AccentColor.colorset/Contents.json",
    "content": "{\n  \"colors\" : [\n    {\n      \"idiom\" : \"universal\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harness/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : \"60x60\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"3x\",\n      \"size\" : \"60x60\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"20x20\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"29x29\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"40x40\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"1x\",\n      \"size\" : \"76x76\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"76x76\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"scale\" : \"2x\",\n      \"size\" : \"83.5x83.5\"\n    },\n    {\n      \"idiom\" : \"ios-marketing\",\n      \"scale\" : \"1x\",\n      \"size\" : \"1024x1024\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harness/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harness/ContentView.swift",
    "content": "//\n//  ContentView.swift\n//  ios-test-harness\n//\n\nimport SwiftUI\n\nstruct ContentView: View {\n    @State var showAlert = false;\n    \n    var body: some View {\n        Button(\"Run Test\") {\n            TestRunner.runTest()\n            showAlert = true\n        }\n        .alert(isPresented: $showAlert) {\n            Alert(title: Text(\"Test Result\"),\n                  message: Text(\"Tests ran without crash!\"))\n        }\n    }\n}\n\nstruct ContentView_Previews: PreviewProvider {\n    static var previews: some View {\n        ContentView()\n    }\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harness/Preview Content/Preview Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harness/ios_test_harnessApp.swift",
    "content": "//\n//  ios_test_harnessApp.swift\n//  ios-test-harness\n//\n\nimport SwiftUI\n\n@main\nstruct ios_test_harnessApp: App {\n    var body: some Scene {\n        WindowGroup {\n            ContentView()\n        }\n    }\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harness.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 55;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t3779698F27A6749700F0EF3C /* ios_test_harnessApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3779698E27A6749700F0EF3C /* ios_test_harnessApp.swift */; };\n\t\t3779699127A6749700F0EF3C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3779699027A6749700F0EF3C /* ContentView.swift */; };\n\t\t3779699327A6749A00F0EF3C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3779699227A6749A00F0EF3C /* Assets.xcassets */; };\n\t\t3779699627A6749A00F0EF3C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3779699527A6749A00F0EF3C /* Preview Assets.xcassets */; };\n\t\t377969A027A6749A00F0EF3C /* ios_test_harnessTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3779699F27A6749A00F0EF3C /* ios_test_harnessTests.swift */; };\n\t\t377969BA27A6755A00F0EF3C /* TestRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377969B927A6755A00F0EF3C /* TestRunner.swift */; };\n\t\t377969C427A6826300F0EF3C /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 377969C327A6826300F0EF3C /* libresolv.tbd */; };\n\t\t37B75D8627AD0A7000D233CA /* libiostest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 37B75D8527AD0A7000D233CA /* libiostest.a */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t3779699C27A6749A00F0EF3C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 3779698327A6749700F0EF3C /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 3779698A27A6749700F0EF3C;\n\t\t\tremoteInfo = \"static-test-harness\";\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t3779698B27A6749700F0EF3C /* ios-test-harness.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = \"ios-test-harness.app\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t3779698E27A6749700F0EF3C /* ios_test_harnessApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_test_harnessApp.swift; sourceTree = \"<group>\"; };\n\t\t3779699027A6749700F0EF3C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = \"<group>\"; };\n\t\t3779699227A6749A00F0EF3C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t3779699527A6749A00F0EF3C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = \"Preview Assets.xcassets\"; sourceTree = \"<group>\"; };\n\t\t3779699B27A6749A00F0EF3C /* ios-test-harnessTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = \"ios-test-harnessTests.xctest\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t3779699F27A6749A00F0EF3C /* ios_test_harnessTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_test_harnessTests.swift; sourceTree = \"<group>\"; };\n\t\t377969B927A6755A00F0EF3C /* TestRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestRunner.swift; sourceTree = \"<group>\"; };\n\t\t377969BB27A675E800F0EF3C /* test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = test.h; sourceTree = \"<group>\"; };\n\t\t377969BC27A6771500F0EF3C /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = \"test-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t377969BD27A67A3A00F0EF3C /* remove-library.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = \"remove-library.sh\"; sourceTree = \"<group>\"; };\n\t\t377969BE27A67A3A00F0EF3C /* create-library.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = \"create-library.sh\"; sourceTree = \"<group>\"; };\n\t\t377969C327A6826300F0EF3C /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = \"sourcecode.text-based-dylib-definition\"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };\n\t\t37B75D8527AD0A7000D233CA /* libiostest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libiostest.a; path = \"test-runner/libiostest.a\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t3779698827A6749700F0EF3C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t37B75D8627AD0A7000D233CA /* libiostest.a in Frameworks */,\n\t\t\t\t377969C427A6826300F0EF3C /* libresolv.tbd in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t3779699827A6749A00F0EF3C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t3779698227A6749700F0EF3C = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t377969B827A6751200F0EF3C /* test-runner */,\n\t\t\t\t3779698D27A6749700F0EF3C /* ios-test-harness */,\n\t\t\t\t3779699E27A6749A00F0EF3C /* ios-test-harnessTests */,\n\t\t\t\t3779698C27A6749700F0EF3C /* Products */,\n\t\t\t\t377969C027A6824C00F0EF3C /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3779698C27A6749700F0EF3C /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3779698B27A6749700F0EF3C /* ios-test-harness.app */,\n\t\t\t\t3779699B27A6749A00F0EF3C /* ios-test-harnessTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3779698D27A6749700F0EF3C /* ios-test-harness */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3779698E27A6749700F0EF3C /* ios_test_harnessApp.swift */,\n\t\t\t\t3779699027A6749700F0EF3C /* ContentView.swift */,\n\t\t\t\t3779699227A6749A00F0EF3C /* Assets.xcassets */,\n\t\t\t\t3779699427A6749A00F0EF3C /* Preview Content */,\n\t\t\t);\n\t\t\tpath = \"ios-test-harness\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3779699427A6749A00F0EF3C /* Preview Content */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3779699527A6749A00F0EF3C /* Preview Assets.xcassets */,\n\t\t\t);\n\t\t\tpath = \"Preview Content\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3779699E27A6749A00F0EF3C /* ios-test-harnessTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3779699F27A6749A00F0EF3C /* ios_test_harnessTests.swift */,\n\t\t\t);\n\t\t\tpath = \"ios-test-harnessTests\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t377969B827A6751200F0EF3C /* test-runner */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t377969BB27A675E800F0EF3C /* test.h */,\n\t\t\t\t377969BC27A6771500F0EF3C /* test-Bridging-Header.h */,\n\t\t\t\t377969BE27A67A3A00F0EF3C /* create-library.sh */,\n\t\t\t\t377969BD27A67A3A00F0EF3C /* remove-library.sh */,\n\t\t\t\t377969B927A6755A00F0EF3C /* TestRunner.swift */,\n\t\t\t);\n\t\t\tpath = \"test-runner\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t377969C027A6824C00F0EF3C /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t37B75D8527AD0A7000D233CA /* libiostest.a */,\n\t\t\t\t377969C327A6826300F0EF3C /* libresolv.tbd */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t3779698A27A6749700F0EF3C /* ios-test-harness */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 377969AF27A6749B00F0EF3C /* Build configuration list for PBXNativeTarget \"ios-test-harness\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t377969BF27A6816900F0EF3C /* create library */,\n\t\t\t\t3779698727A6749700F0EF3C /* Sources */,\n\t\t\t\t3779698827A6749700F0EF3C /* Frameworks */,\n\t\t\t\t3779698927A6749700F0EF3C /* Resources */,\n\t\t\t\t377969C527A682E200F0EF3C /* delete library */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = \"ios-test-harness\";\n\t\t\tproductName = \"static-test-harness\";\n\t\t\tproductReference = 3779698B27A6749700F0EF3C /* ios-test-harness.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t3779699A27A6749A00F0EF3C /* ios-test-harnessTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 377969B227A6749B00F0EF3C /* Build configuration list for PBXNativeTarget \"ios-test-harnessTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t3779699727A6749A00F0EF3C /* Sources */,\n\t\t\t\t3779699827A6749A00F0EF3C /* Frameworks */,\n\t\t\t\t3779699927A6749A00F0EF3C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t3779699D27A6749A00F0EF3C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"ios-test-harnessTests\";\n\t\t\tproductName = \"static-test-harnessTests\";\n\t\t\tproductReference = 3779699B27A6749A00F0EF3C /* ios-test-harnessTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t3779698327A6749700F0EF3C /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = 1;\n\t\t\t\tLastSwiftUpdateCheck = 1320;\n\t\t\t\tLastUpgradeCheck = 1320;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t3779698A27A6749700F0EF3C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 13.2.1;\n\t\t\t\t\t};\n\t\t\t\t\t3779699A27A6749A00F0EF3C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 13.2.1;\n\t\t\t\t\t\tTestTargetID = 3779698A27A6749700F0EF3C;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 3779698627A6749700F0EF3C /* Build configuration list for PBXProject \"ios-test-harness\" */;\n\t\t\tcompatibilityVersion = \"Xcode 13.0\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 3779698227A6749700F0EF3C;\n\t\t\tproductRefGroup = 3779698C27A6749700F0EF3C /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t3779698A27A6749700F0EF3C /* ios-test-harness */,\n\t\t\t\t3779699A27A6749A00F0EF3C /* ios-test-harnessTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t3779698927A6749700F0EF3C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t3779699627A6749A00F0EF3C /* Preview Assets.xcassets in Resources */,\n\t\t\t\t3779699327A6749A00F0EF3C /* Assets.xcassets in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t3779699927A6749A00F0EF3C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t377969BF27A6816900F0EF3C /* create library */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"create library\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t\t\"$(DERIVED_FILE_DIR)/libiostest.a\",\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"source ${PROJECT_DIR}/test-runner/create-library.sh\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t377969C527A682E200F0EF3C /* delete library */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputFileListPaths = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"delete library\";\n\t\t\toutputFileListPaths = (\n\t\t\t);\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"source ${PROJECT_DIR}/test-runner/remove-library.sh\\n\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t3779698727A6749700F0EF3C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t3779699127A6749700F0EF3C /* ContentView.swift in Sources */,\n\t\t\t\t377969BA27A6755A00F0EF3C /* TestRunner.swift in Sources */,\n\t\t\t\t3779698F27A6749700F0EF3C /* ios_test_harnessApp.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t3779699727A6749A00F0EF3C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t377969A027A6749A00F0EF3C /* ios_test_harnessTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t3779699D27A6749A00F0EF3C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 3779698A27A6749700F0EF3C /* ios-test-harness */;\n\t\t\ttargetProxy = 3779699C27A6749A00F0EF3C /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\t377969AD27A6749B00F0EF3C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t377969AE27A6749B00F0EF3C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-O\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t377969B027A6749B00F0EF3C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_ASSET_PATHS = \"\\\"ios-test-harness/Preview Content\\\"\";\n\t\t\t\tDEVELOPMENT_TEAM = 85H73V9R3F;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchScreen_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(DERIVED_FILES_DIR)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/test-runner\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.brotsky.ios-test-harness\";\n\t\t\t\tPRODUCT_NAME = \"ios-test-harness\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"$(PROJECT_DIR)/test-runner/test-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t377969B127A6749B00F0EF3C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_ASSET_PATHS = \"\\\"ios-test-harness/Preview Content\\\"\";\n\t\t\t\tDEVELOPMENT_TEAM = 85H73V9R3F;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchScreen_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(DERIVED_FILES_DIR)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/test-runner\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.brotsky.ios-test-harness\";\n\t\t\t\tPRODUCT_NAME = \"ios-test-harness\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"$(PROJECT_DIR)/test-runner/test-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t377969B327A6749B00F0EF3C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = 85H73V9R3F;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.2;\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.brotsky.static-test-harnessTests\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = NO;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/ios-test-harness.app/ios-test-harness\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t377969B427A6749B00F0EF3C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = 85H73V9R3F;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.2;\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"com.brotsky.static-test-harnessTests\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = NO;\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/ios-test-harness.app/ios-test-harness\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t3779698627A6749700F0EF3C /* Build configuration list for PBXProject \"ios-test-harness\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t377969AD27A6749B00F0EF3C /* Debug */,\n\t\t\t\t377969AE27A6749B00F0EF3C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t377969AF27A6749B00F0EF3C /* Build configuration list for PBXNativeTarget \"ios-test-harness\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t377969B027A6749B00F0EF3C /* Debug */,\n\t\t\t\t377969B127A6749B00F0EF3C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t377969B227A6749B00F0EF3C /* Build configuration list for PBXNativeTarget \"ios-test-harnessTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t377969B327A6749B00F0EF3C /* Debug */,\n\t\t\t\t377969B427A6749B00F0EF3C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 3779698327A6749700F0EF3C /* Project object */;\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/ios-test-harnessTests/ios_test_harnessTests.swift",
    "content": "//\n//  static_test_harnessTests.swift\n//  static-test-harnessTests\n//\n//  Created by Daniel Brotsky on 1/29/22.\n//\n\nimport XCTest\n@testable import ios_test_harness\n\nclass static_test_harnessTests: XCTestCase {\n\n    func testRun() throws {\n        TestRunner.runTest()\n    }\n\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/test-runner/TestRunner.swift",
    "content": "//\n// TestRunner.swift\n// ios-test-harness\n//\n\nimport Foundation\n\nclass TestRunner {\n    static func runTest() {\n        test()\n    }\n}\n"
  },
  {
    "path": "iostest/ios-test-harness/test-runner/create-library.sh",
    "content": "#!/bin/bash\nset -x\n# create-library.sh\n# Build the correct Rust target and place\n# the resulting library in the build products\n#\n# The $PATH used by Xcode likely won't contain Cargo, fix that.\n# In addition, the $PATH used by XCode has lots of Apple-specific\n# developer tools that your Cargo isn't expecting to use, fix that.\n# Note: This assumes a default `rustup` setup and default path.\nbuild_path=\"$HOME/.cargo/bin:/usr/local/bin:/usr/bin:/bin\"\n#\n# Figure out the correct Rust target from the ARCHS and PLATFORM.\n# This script expects just one element in ARCHS.\ncase \"$ARCHS\" in\n\t\"arm64\")\trust_arch=\"aarch64\" ;;\n\t\"x86_64\")\trust_arch=\"x86_64\" ;;\n\t*)\t\t\techo \"error: unsupported architecture: $ARCHS\" ;;\nesac\nif [[ \"$PLATFORM_NAME\" == \"macosx\" ]]; then\n\trust_platform=\"apple-darwin\"\nelse\n\trust_platform=\"apple-ios\"\nfi\nif [[ \"$PLATFORM_NAME\" == \"iphonesimulator\" ]]; then\n    if [[ \"${rust_arch}\" == \"aarch64\" ]]; then\n        rust_abi=\"-sim\"\n    else\n        rust_abi=\"\"\n    fi\nelse\n\trust_abi=\"\"\nfi\nrust_target=\"${rust_arch}-${rust_platform}${rust_abi}\"\n#\n# Build library in debug or release\nbuild_args=(--manifest-path ../Cargo.toml --target \"${rust_target}\")\nif [[ \"$CONFIGURATION\" == \"Release\" ]]; then\n\trust_config=\"release\"\n\tenv PATH=\"${build_path}\" cargo build --release \"${build_args[@]}\"\nelif [[ \"$CONFIGURATION\" == \"Debug\" ]]; then\n\trust_config=\"debug\"\n\tenv PATH=\"${build_path}\" cargo build \"${build_args[@]}\"\nelse\n    echo \"error: Unexpected build configuration: $CONFIGURATION\"\nfi\n#\n# Copy the built library to the derived files directory\ncp -v \"../../target/${rust_target}/${rust_config}/libiostest.a\" ${DERIVED_FILES_DIR}\n"
  },
  {
    "path": "iostest/ios-test-harness/test-runner/remove-library.sh",
    "content": "#!/bin/sh\nset -x\n# delete-library.sh\n# Remove the build Rust library so it will be rebuilt next time.\n#\nrm -fv ${DERIVED_FILES_DIR}/libiostest.a\n"
  },
  {
    "path": "iostest/ios-test-harness/test-runner/test-Bridging-Header.h",
    "content": "//\n// test-Bridging-Header.h\n// ios-test-harness\n//\n\n#ifndef test_Bridging_Header_h\n#define test_Bridging_Header_h\n\n#import \"test.h\"\n\n#endif /* test_Bridging_Header_h */\n"
  },
  {
    "path": "iostest/ios-test-harness/test-runner/test.h",
    "content": "//\n// test.h\n// ios-test-harness\n//\n\n#ifndef test_h\n#define test_h\n\nextern void test();\n\n#endif /* test_h */\n"
  },
  {
    "path": "iostest/src/lib.rs",
    "content": "#![allow(deprecated)]\n//! Test library for newer iOS-style APIs.\n//!\n//! This library exercises the iOS-style password APIs.\n//! It will compile under either macOS or iOS, so that\n//! it can be linked into a test-harness executable\n//! on either platform.  Since Rust provides a built-in\n//! facility for testing, this library is really only\n//! useful when built for iOS.  See the ios-test-harness\n//! XCode project (part of this crate) for how it gets\n//! linked and used for testing.\n\nuse security_framework::passwords::{\n    delete_generic_password, delete_internet_password, get_generic_password, get_internet_password,\n    set_generic_password, set_internet_password,\n};\nuse security_framework_sys::base::errSecItemNotFound;\nuse security_framework_sys::keychain::SecAuthenticationType::Any;\nuse security_framework_sys::keychain::SecProtocolType::HTTP;\n\n#[no_mangle]\nextern \"C\" fn test() {\n    test_missing_generic_password();\n    test_round_trip_empty_generic_password();\n    test_round_trip_ascii_generic_password();\n    test_round_trip_non_ascii_generic_password();\n    test_round_trip_non_utf8_generic_password();\n    test_update_generic_password();\n    test_missing_internet_password();\n    test_round_trip_empty_internet_password();\n    test_round_trip_ascii_internet_password();\n    test_round_trip_non_ascii_internet_password();\n    test_round_trip_non_utf8_internet_password();\n    test_update_internet_password();\n}\n\nfn test_missing_generic_password() {\n    println!(\"test_missing_generic_password: start\");\n    let name = \"test_missing_generic_password\";\n    let result = delete_generic_password(name, name);\n    match result {\n        Ok(()) => (),\n        Err(err) if err.code() == errSecItemNotFound => (),\n        Err(err) => panic!(\"test_missing_generic_password: delete failed with status: {}\", err.code()),\n    }\n    let result = get_generic_password(name, name);\n    match result {\n        Ok(bytes) => panic!(\"test_missing_password: get returned {bytes:?}\"),\n        Err(err) if err.code() == errSecItemNotFound => (),\n        Err(err) => panic!(\"test_missing_generic_password: get failed with status: {}\", err.code()),\n    }\n    let result = delete_generic_password(name, name);\n    match result {\n        Ok(()) => panic!(\"test_missing_generic_password: second delete found a password\"),\n        Err(err) if err.code() == errSecItemNotFound => (),\n        Err(err) => panic!(\"test_missing_generic_password: delete failed with status: {}\", err.code()),\n    }\n    println!(\"test_missing_generic_password: pass\");\n}\n\nfn test_round_trip_empty_generic_password() {\n    println!(\"test_round_trip_empty_generic_password: start\");\n    let name = \"test_empty_generic_password_input\";\n    let in_pass = b\"\";\n    set_generic_password(name, name, in_pass).unwrap();\n    let out_pass = get_generic_password(name, name).unwrap();\n    assert_eq!(in_pass.as_slice(), out_pass);\n    delete_generic_password(name, name).unwrap();\n    println!(\"test_round_trip_empty_generic_password: pass\");\n}\n\nfn test_round_trip_ascii_generic_password() {\n    println!(\"test_round_trip_ascii_generic_password: start\");\n    let name = \"test_round_trip_ascii_generic_password\";\n    let password = b\"test ascii password\";\n    set_generic_password(name, name, password).unwrap();\n    let stored_password = get_generic_password(name, name).unwrap();\n    assert_eq!(password.as_slice(), stored_password);\n    delete_generic_password(name, name).unwrap();\n    println!(\"test_round_trip_ascii_generic_password: pass\");\n}\n\nfn test_round_trip_non_ascii_generic_password() {\n    println!(\"test_round_trip_non_ascii_generic_password: start\");\n    let name = \"test_round_trip_non_ascii_generic_password\";\n    let password = \"このきれいな花は桜です\".as_bytes();\n    set_generic_password(name, name, password).unwrap();\n    let stored_password = get_generic_password(name, name).unwrap();\n    assert_eq!(stored_password, password);\n    delete_generic_password(name, name).unwrap();\n    println!(\"test_round_trip_non_ascii_generic_password: pass\");\n}\n\nfn test_round_trip_non_utf8_generic_password() {\n    println!(\"test_round_trip_non_utf8_generic_password: start\");\n    let name = \"test_round_trip_non_utf8_generic_password\";\n    let password: [u8; 10] = [0, 121, 122, 123, 40, 50, 126, 127, 8, 9];\n    set_generic_password(name, name, &password).unwrap();\n    let stored_password = get_generic_password(name, name).unwrap();\n    assert_eq!(stored_password, password);\n    delete_generic_password(name, name).unwrap();\n    println!(\"test_round_trip_non_utf8_generic_password: pass\");\n}\n\nfn test_update_generic_password() {\n    println!(\"test_update_generic_password: start\");\n    let name = \"test_update_generic_password\";\n    let password = b\"test ascii password\".as_slice();\n    set_generic_password(name, name, password).unwrap();\n    let stored_password = get_generic_password(name, name).unwrap();\n    assert_eq!(stored_password, password);\n    let password = \"このきれいな花は桜です\".as_bytes();\n    set_generic_password(name, name, password).unwrap();\n    let stored_password = get_generic_password(name, name).unwrap();\n    assert_eq!(stored_password, password);\n    delete_generic_password(name, name).unwrap();\n    println!(\"test_update_generic_password: pass\");\n}\n\nfn test_missing_internet_password() {\n    println!(\"test_missing_internet_password: start\");\n    let name = \"test_missing_internet_password\";\n    let result = delete_internet_password(name, None, name, \"/test\", None, HTTP, Any);\n    match result {\n        Ok(()) => (),\n        Err(err) if err.code() == errSecItemNotFound => (),\n        Err(err) => panic!(\"test_missing_internet_password: delete failed with status: {}\", err.code()),\n    }\n    let result = get_internet_password(name, None, name, \"/test\", None, HTTP, Any);\n    match result {\n        Ok(bytes) => panic!(\"test_missing_password: get returned {bytes:?}\"),\n        Err(err) if err.code() == errSecItemNotFound => (),\n        Err(err) => panic!(\"test_missing_internet_password: get failed with status: {}\", err.code()),\n    }\n    let result = delete_internet_password(name, None, name, \"/test\", None, HTTP, Any);\n    match result {\n        Ok(()) => panic!(\"test_missing_internet_password: second delete found a password\"),\n        Err(err) if err.code() == errSecItemNotFound => (),\n        Err(err) => panic!(\"test_missing_internet_password: delete failed with status: {}\", err.code()),\n    }\n    println!(\"test_missing_internet_password: pass\");\n}\n\nfn test_round_trip_empty_internet_password() {\n    println!(\"test_round_trip_empty_internet_password: start\");\n    let name = \"test_empty_internet_password_input\";\n    let in_pass = b\"\".as_slice();\n    set_internet_password(name, None, name, \"/test\", None, HTTP, Any, in_pass).unwrap();\n    let out_pass = get_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    assert_eq!(in_pass, out_pass);\n    delete_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    println!(\"test_round_trip_empty_internet_password: pass\");\n}\n\nfn test_round_trip_ascii_internet_password() {\n    println!(\"test_round_trip_ascii_internet_password: start\");\n    let name = \"test_round_trip_ascii_internet_password\";\n    let password = b\"test ascii password\".as_slice();\n    set_internet_password(name, None, name, \"/test\", None, HTTP, Any, password).unwrap();\n    let stored_password = get_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    assert_eq!(stored_password, password);\n    delete_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    println!(\"test_round_trip_ascii_internet_password: pass\");\n}\n\nfn test_round_trip_non_ascii_internet_password() {\n    println!(\"test_round_trip_non_ascii_internet_password: start\");\n    let name = \"test_round_trip_non_ascii_internet_password\";\n    let password = \"このきれいな花は桜です\".as_bytes();\n    set_internet_password(name, None, name, \"/test\", None, HTTP, Any, password).unwrap();\n    let stored_password = get_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    assert_eq!(stored_password, password);\n    delete_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    println!(\"test_round_trip_non_ascii_internet_password: pass\");\n}\n\nfn test_round_trip_non_utf8_internet_password() {\n    println!(\"test_round_trip_non_utf8_internet_password: start\");\n    let name = \"test_round_trip_non_utf8_internet_password\";\n    let password: [u8; 10] = [0, 121, 122, 123, 40, 50, 126, 127, 8, 9];\n    set_internet_password(name, None, name, \"/test\", None, HTTP, Any, &password).unwrap();\n    let stored_password = get_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    assert_eq!(stored_password, password.as_slice());\n    delete_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    println!(\"test_round_trip_non_utf8_internet_password: pass\");\n}\n\nfn test_update_internet_password() {\n    println!(\"test_update_internet_password: start\");\n    let name = \"test_update_internet_password\";\n    let password = b\"test ascii password\".as_slice();\n    set_internet_password(name, None, name, \"/test\", None, HTTP, Any, password).unwrap();\n    let stored_password = get_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    assert_eq!(stored_password, password);\n    let password = \"このきれいな花は桜です\".as_bytes();\n    set_internet_password(name, None, name, \"/test\", None, HTTP, Any, password).unwrap();\n    let stored_password = get_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    assert_eq!(stored_password, password);\n    delete_internet_password(name, None, name, \"/test\", None, HTTP, Any).unwrap();\n    println!(\"test_update_internet_password: pass\");\n}\n"
  },
  {
    "path": "iostest/tests/ios_macos.rs",
    "content": "//! Tests of legacy macOS versus newer iOS-style APIs.\n//!\n//! These tests compile under both iOS and macOS.  Of course, there's not\n//! much point compiling them under iOS, since you can't run them under iOS,\n//! but at least the compilation tells you that the interfaces are intact.\n//! For iOS testing, compile the library and use the included ios-test-harness.\n//!\n//! NOTE: Some of these tests involve keychain queries for multiple items,\n//! and experience shows that running multiple keychain queries on separate\n//! threads in the same process simultaneously can produce interference.\n//! So all the query tests have been conditioned to run serially.\n\nuse core_foundation::base::TCFType;\nuse core_foundation::string::CFString;\nuse security_framework::item::{ItemClass, ItemSearchOptions, Limit, SearchResult};\n#[cfg(target_os = \"macos\")]\nuse security_framework::os::macos::keychain::SecKeychain;\nuse security_framework::passwords::{delete_generic_password, set_generic_password};\nuse security_framework_sys::item::{kSecAttrAccount, kSecAttrService};\nuse serial_test::serial;\n\n#[test]\n#[serial]\nfn insert_then_find_generic() {\n    let service_key = format!(\"{}\", unsafe { CFString::wrap_under_get_rule(kSecAttrService) });\n    let mut names = vec![];\n    for _ in 0..4 {\n        let name = generate_random_string();\n        set_generic_password(&name, &name, name.as_bytes()).unwrap();\n        names.push(name);\n    }\n    let results = ItemSearchOptions::new()\n        .class(ItemClass::generic_password())\n        .load_attributes(true)\n        .limit(Limit::All)\n        .search()\n        .unwrap();\n    assert!(results.len() >= names.len());\n    let mut found = 0;\n    for result in &results {\n        match result {\n            SearchResult::Dict(_) => {\n                let dict = result.simplify_dict().unwrap();\n                if let Some(val) = dict.get(&service_key) {\n                    if names.contains(val) {\n                        found += 1;\n                    }\n                }\n            },\n            _ => panic!(\"Got a non-dictionary from a password search\"),\n        }\n    }\n    assert_eq!(names.len(), found);\n    for name in &names {\n        delete_generic_password(name, name).unwrap();\n    }\n}\n\n#[test]\n#[serial]\n#[cfg(target_os = \"macos\")]\nfn insert_then_find_generic_legacy() {\n    let keychain = SecKeychain::default().unwrap();\n    let service_key = format!(\"{}\", unsafe { CFString::wrap_under_get_rule(kSecAttrService) });\n    // create 4 legacy and 4 modern generic passwords\n    let mut legacy_names = vec![];\n    for _ in 0..4 {\n        let name = generate_random_string();\n        keychain.set_generic_password(&name, &name, name.as_bytes()).unwrap();\n        legacy_names.push(name);\n    }\n    let mut modern_names = vec![];\n    for _ in 0..4 {\n        let name = generate_random_string();\n        set_generic_password(&name, &name, name.as_bytes()).unwrap();\n        modern_names.push(name);\n    }\n    // first check to see that the legacy passwords are found by the modern search\n    let results = ItemSearchOptions::new()\n        .class(ItemClass::generic_password())\n        .load_attributes(true)\n        .limit(Limit::All)\n        .search()\n        .unwrap();\n    assert!(results.len() >= legacy_names.len());\n    let mut found = 0;\n    for result in &results {\n        match result {\n            SearchResult::Dict(_) => {\n                let dict = result.simplify_dict().unwrap();\n                if let Some(val) = dict.get(&service_key) {\n                    if legacy_names.contains(val) {\n                        found += 1;\n                    }\n                }\n            },\n            _ => panic!(\"Got a non-dictionary from a password search\"),\n        }\n    }\n    assert_eq!(legacy_names.len(), found);\n    // next check to see that the modern passwords are found by the legacy search\n    for name in &modern_names {\n        keychain.find_generic_password(name, name).unwrap();\n    }\n    // finally delete both the legacy and the modern passwords\n    for name in &legacy_names {\n        let (_, item) = keychain.find_generic_password(name, name).unwrap();\n        item.delete();\n    }\n    for name in &modern_names {\n        delete_generic_password(name, name).unwrap();\n    }\n}\n\n#[test]\n#[serial]\nfn find_leftover_test_generic_passwords() {\n    let service_key = format!(\"{}\", unsafe { CFString::wrap_under_get_rule(kSecAttrService) });\n    let username_key = format!(\"{}\", unsafe { CFString::wrap_under_get_rule(kSecAttrAccount) });\n    let mut found: Vec<String> = vec![];\n    let results = ItemSearchOptions::new()\n        .class(ItemClass::generic_password())\n        .load_attributes(true)\n        .limit(Limit::All)\n        .search()\n        .unwrap();\n    for result in &results {\n        match result {\n            SearchResult::Dict(_) => {\n                let dict = result.simplify_dict().unwrap();\n                if let Some(val) = dict.get(&service_key) {\n                    if val.len() == 30 {\n                        if let Some(val2) = dict.get(&username_key) {\n                            if val2.eq(val) {\n                                // println!(\"Found left-over test-created entry: {}\", val);\n                                found.push(val.clone());\n                            }\n                        }\n                    }\n                }\n            },\n            _ => panic!(\"Got a non-dictionary from a password search\"),\n        }\n    }\n    assert!(found.is_empty(), \"There are {} entries created by older tests: {:?}\",\n            found.len(),\n            &found);\n}\n\nfn generate_random_string() -> String {\n    // from the Rust Cookbook:\n    // https://rust-lang-nursery.github.io/rust-cookbook/algorithms/randomness.html\n    use rand::{distributions::Alphanumeric, thread_rng, Rng};\n    thread_rng()\n        .sample_iter(&Alphanumeric)\n        .take(30)\n        .map(char::from)\n        .collect()\n}\n"
  },
  {
    "path": "security-framework/Cargo.toml",
    "content": "[package]\nname = \"security-framework\"\nversion = \"3.7.1\"\nauthors = [\n    \"Steven Fackler <sfackler@gmail.com>\",\n    \"Kornel <kornel@geekhood.net>\",\n]\nlicense = \"MIT OR Apache-2.0\"\ndescription = \"Security.framework bindings for macOS and iOS\"\nrepository = \"https://github.com/kornelski/rust-security-framework\"\ndocumentation = \"https://docs.rs/security_framework\"\nhomepage = \"https://lib.rs/crates/security_framework\"\ncategories = [\"os::macos-apis\", \"cryptography\", \"api-bindings\"]\nreadme = \"README.md\"\nkeywords = [\"iOS\", \"TLS\", \"SSL\", \"crypto\", \"keychain\"]\nexclude = [\"test/*\"]\nedition = \"2024\"\nrust-version = \"1.85\"\n\n[dependencies]\nsecurity-framework-sys = { version = \"2.17\", default-features = false, path = \"../security-framework-sys\" }\nbitflags = \"2.11\"\ncore-foundation = \"0.10\"\ncore-foundation-sys = \"0.8.6\"\nlibc = \"0.2.139\"\nlog = { version = \"0.4.20\", optional = true }\n\n[dev-dependencies]\nhex = \"0.4.3\"\nenv_logger = \"0.11\"\nx509-parser = \"0.18\"\ntime = \"0.3.23\"\ntempfile = \"3.12.0\"\n\n[features]\ndefault = [\"OSX_10_14\", \"alpn\", \"session-tickets\"]\n# Always enabled\nalpn = []\n# Always enabled\nsession-tickets = []\njob-bless = []\n# Enables `GenerateKeyOptions::set_synchronizable`. Warning: not backwards-compatible!\nsync-keychain = [\"OSX_10_13\"]\n\n# Always enabled\nOSX_10_12 = []\n# Always enabled\nOSX_10_13 = []\n# Always enabled\nOSX_10_14 = []\nOSX_10_15 = [\"security-framework-sys/OSX_10_15\"]\n# Enable features that require macOS 12\nmacos-12 = [\"security-framework-sys/macos-12\"]\n\nnightly = [] # not used, doesn't do anything, only for back compat\n\n[lints]\nworkspace = true\n\n[[example]]\nname = \"client\"\n\n[[example]]\nname = \"find_internet_password\"\n\n[[example]]\nname = \"set_internet_password\"\n\n[package.metadata.docs.rs]\ntargets = [\"x86_64-apple-darwin\", \"aarch64-apple-ios\"]\nfeatures = [\"OSX_10_15\"]\n\n[badges]\nmaintenance = { status = \"looking-for-maintainer\" }\n"
  },
  {
    "path": "security-framework/THIRD_PARTY",
    "content": "This project contains documentation adapted from Apple Inc.'s Security Framework\nunder the following license:\n\nAPPLE PUBLIC SOURCE LICENSE\nVersion 2.0 -  August 6, 2003\n\nPlease read this License carefully before downloading this software.  By downloading or using this software, you are agreeing to be bound by the terms of this License.  If you do not or cannot agree to the terms of this License, please do not download or use the software.\n\nApple Note:  In January 2007, Apple changed its corporate name from \"Apple Computer, Inc.\" to \"Apple Inc.\"  This change has been reflected below and copyright years updated, but no other changes have been made to the APSL 2.0.\n\n1.  General; Definitions.  This License applies to any program or other work which Apple Inc. (\"Apple\") makes publicly available and which contains a notice placed by Apple identifying such program or work as \"Original Code\" and stating that it is subject to the terms of this Apple Public Source License version 2.0 (\"License\").  As used in this License:\n\n1.1  \"Applicable Patent Rights\" mean:  (a) in the case where Apple is the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to Apple and (ii) that cover subject matter contained in the Original Code, but only to the extent necessary to use, reproduce and/or distribute the Original Code without infringement; and (b) in the case where You are the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to You and (ii) that cover subject matter in Your Modifications, taken alone or in combination with Original Code.\n\n1.2 \"Contributor\" means any person or entity that creates or contributes to the creation of Modifications.\n\n1.3  \"Covered Code\" means the Original Code, Modifications, the combination of Original Code and any Modifications, and/or any respective portions thereof.\n\n1.4 \"Externally Deploy\" means: (a) to sublicense, distribute or otherwise make Covered Code available, directly or indirectly, to anyone other than You; and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way to provide a service, including but not limited to delivery of content, through electronic communication with a client other than You.\n\n1.5 \"Larger Work\" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License.\n\n1.6 \"Modifications\" mean any addition to, deletion from, and/or change to, the substance and/or structure of the Original Code, any previous Modifications, the combination of Original Code and any previous Modifications, and/or any respective portions thereof.  When code is released as a series of files, a Modification is:  (a) any addition to or deletion from the contents of a file containing Covered Code; and/or (b) any new file or other representation of computer program statements that contains any part of Covered Code. \n\n1.7 \"Original Code\" means (a) the Source Code of a program or other work as originally made available by Apple under this License, including the Source Code of any updates or upgrades to such programs or works made available by Apple under this License, and that has been expressly identified by Apple as such in the header file(s) of such work; and (b) the object code compiled from such Source Code and originally made available by Apple under this License\n\n1.8 \"Source Code\" means the human readable form of a program or other work that is suitable for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an executable (object code).\n\n1.9 \"You\" or \"Your\" means an individual or a legal entity exercising rights under this License.  For legal entities, \"You\" or \"Your\" includes any entity which controls, is controlled by, or is under common control with, You, where \"control\" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity.\n\n2.  Permitted Uses; Conditions & Restrictions.   Subject to the terms and conditions of this License, Apple hereby grants You, effective on the date You accept this License and download the Original Code, a world-wide, royalty-free, non-exclusive license, to the extent of Apple's Applicable Patent Rights and copyrights covering the Original Code, to do the following:\n\n2.1 Unmodified Code.  You may use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy verbatim, unmodified copies of the Original Code, for commercial or non-commercial purposes, provided that in each instance:\n\n(a) You must retain and reproduce in all copies of Original Code the copyright and other proprietary notices and disclaimers of Apple as they appear in the Original Code, and keep intact all notices in the Original Code that refer to this License; and\n\n(b)     You must include a copy of this License with every copy of Source Code of Covered Code and documentation You distribute or Externally Deploy, and You may not offer or impose any terms on such Source Code that alter or restrict this License or the recipients' rights hereunder, except as permitted under Section 6.\n\n2.2 Modified Code.  You may modify Covered Code and use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy Your Modifications and Covered Code, for commercial or non-commercial purposes, provided that in each instance You also meet all of these conditions:\n\n(a) You must satisfy all the conditions of Section 2.1 with respect to the Source Code of the Covered Code; \n\n(b) You must duplicate, to the extent it does not already exist, the notice in Exhibit A in each file of the Source Code of all Your Modifications, and cause the modified files to carry prominent notices stating that You changed the files and the date of any change; and\n\n(c) If You Externally Deploy Your Modifications, You must make Source Code of all Your Externally Deployed Modifications either available to those to whom You have Externally Deployed Your Modifications, or publicly available.  Source Code of Your Externally Deployed Modifications must be released under the terms set forth in this License, including the license grants set forth in Section 3 below, for as long as you Externally Deploy the Covered Code or twelve (12) months from the date of initial External Deployment, whichever is longer. You should preferably distribute the Source Code of Your Externally Deployed Modifications electronically (e.g. download from a web site).\n\n2.3 Distribution of Executable Versions.  In addition, if You Externally Deploy Covered Code (Original Code and/or Modifications) in object code, executable form only, You must include a prominent notice, in the code itself as well as in related documentation, stating that Source Code of the Covered Code is available under the terms of this License with information on how and where to obtain such Source Code.  \n\n2.4 Third Party Rights.  You expressly acknowledge and agree that although Apple and each Contributor grants the licenses to their respective portions of the Covered Code set forth herein, no assurances are provided by Apple or any Contributor that the Covered Code does not infringe the patent or other intellectual property rights of any other entity. Apple and each Contributor disclaim any liability to You for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, You hereby assume sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow You to distribute the Covered Code, it is Your responsibility to acquire that license before distributing the Covered Code.\n\n3.  Your Grants.  In consideration of, and as a condition to, the licenses granted to You under this License, You hereby grant to any person or entity receiving or distributing Covered Code under this License a non-exclusive, royalty-free, perpetual, irrevocable license, under Your Applicable Patent Rights and other intellectual property rights (other than patent) owned or controlled by You, to use, reproduce, display, perform, modify, sublicense, distribute and Externally Deploy Your Modifications of the same scope and extent as Apple's licenses under Sections 2.1 and 2.2 above.  \n\n4.  Larger Works.  You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product.  In each such instance, You must make sure the requirements of this License are fulfilled for the Covered Code or any portion thereof. \n\n5.  Limitations on Patent License.   Except as expressly stated in Section 2, no other patent rights, express or implied, are granted by Apple herein.  Modifications and/or Larger Works may require additional patent licenses from Apple which Apple may grant in its sole discretion.  \n\n6.  Additional Terms.  You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations and/or other rights consistent with the scope of the license granted herein (\"Additional Terms\") to one or more recipients of Covered Code. However, You may do so only on Your own behalf and as Your sole responsibility, and not on behalf of Apple or any Contributor. You must obtain the recipient's agreement that any such Additional Terms are offered by You alone, and You hereby agree to indemnify, defend and hold Apple and every Contributor harmless for any liability incurred by or claims asserted against Apple or such Contributor by reason of any such Additional Terms. \n\n7.  Versions of the License.  Apple may publish revised and/or new versions of this License from time to time.  Each version will be given a distinguishing version number.  Once Original Code has been published under a particular version of this License, You may continue to use it under the terms of that version. You may also choose to use such Original Code under the terms of any subsequent version of this License published by Apple.  No one other than Apple has the right to modify the terms applicable to Covered Code created under this License.  \n\n8.  NO WARRANTY OR SUPPORT.  The Covered Code may contain in whole or in part pre-release, untested, or not fully tested works.  The Covered Code may contain errors that could cause failures or loss of data, and may be incomplete or contain inaccuracies.  You expressly acknowledge and agree that use of the Covered Code, or any portion thereof, is at Your sole and entire risk.  THE COVERED CODE IS PROVIDED \"AS IS\" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS \"APPLE\" FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED.  NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.  You acknowledge that the Covered Code is not intended for use in the operation of nuclear facilities, aircraft navigation, communication systems, or air traffic control machines in which case the failure of the Covered Code could lead to death, personal injury, or severe physical or environmental damage.\n\n9.  LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. In no event shall Apple's total liability to You for all damages (other than as may be required by applicable law) under this License exceed the amount of fifty dollars ($50.00).\n\n10. Trademarks.  This License does not grant any rights to use the trademarks or trade names  \"Apple\", \"Mac\", \"Mac OS\", \"QuickTime\", \"QuickTime Streaming Server\" or any other trademarks, service marks, logos or trade names belonging to Apple (collectively \"Apple Marks\") or to any trademark, service mark, logo or trade name belonging to any Contributor.  You agree not to use any Apple Marks in or as part of the name of products derived from the Original Code or to endorse or promote products derived from the Original Code other than as expressly permitted by and in strict compliance at all times with Apple's third party trademark usage guidelines which are posted at http://www.apple.com/legal/guidelinesfor3rdparties.html.  \n\n11. Ownership. Subject to the licenses granted under this License, each Contributor retains all rights, title and interest in and to any Modifications made by such Contributor.  Apple retains all rights, title and interest in and to the Original Code and any Modifications made by or on behalf of Apple (\"Apple Modifications\"), and such Apple Modifications will not be automatically subject to this License.  Apple may, at its sole discretion, choose to license such Apple Modifications under this License, or on different terms from those contained in this License or may choose not to license them at all.  \n\n12. Termination.  \n\n12.1    Termination.  This License and the rights granted hereunder will terminate:\n\n(a) automatically without notice from Apple if You fail to comply with any term(s) of this License and fail to cure such breach within 30 days of becoming aware of such breach;\n(b) immediately in the event of the circumstances described in Section 13.5(b); or\n(c) automatically without notice from Apple if You, at any time during the term of this License, commence an action for patent infringement against Apple; provided that Apple did not first commence an action for patent infringement against You in that instance.\n\n12.2    Effect of Termination.  Upon termination, You agree to immediately stop any further use, reproduction, modification, sublicensing and distribution of the Covered Code.  All sublicenses to the Covered Code which have been properly granted prior to termination shall survive any termination of this License.  Provisions which, by their nature, should remain in effect beyond the termination of this License shall survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, 12.2 and 13.  No party will be liable to any other for compensation, indemnity or damages of any sort solely as a result of terminating this License in accordance with its terms, and termination of this License will be without prejudice to any other right or remedy of any party.\n\n13.     Miscellaneous.\n\n13.1    Government End Users.   The Covered Code is a \"commercial item\" as defined in FAR 2.101.  Government software and technical data rights in the Covered Code include only those rights customarily provided to the public as defined in this License. This customary commercial license in technical data and software is provided in accordance with FAR 12.211 (Technical Data) and 12.212 (Computer Software) and, for Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in Commercial Computer Software or Computer Software Documentation).  Accordingly, all U.S. Government End Users acquire Covered Code with only those rights set forth herein.\n\n13.2    Relationship of Parties.  This License will not be construed as creating an agency, partnership, joint venture or any other form of legal association between or among You, Apple or any Contributor, and You will not represent to the contrary, whether expressly, by implication, appearance or otherwise.\n\n13.3    Independent Development.   Nothing in this License will impair Apple's right to acquire, license, develop, have others develop for it, market and/or distribute technology or products that perform the same or similar functions as, or otherwise compete with, Modifications, Larger Works, technology or products that You may develop, produce, market or distribute.\n\n13.4    Waiver; Construction.  Failure by Apple or any Contributor to enforce any provision of this License will not be deemed a waiver of future enforcement of that or any other provision.  Any law or regulation which provides that the language of a contract shall be construed against the drafter will not apply to this License.\n\n13.5    Severability.  (a) If for any reason a court of competent jurisdiction finds any provision of this License, or portion thereof, to be unenforceable, that provision of the License will be enforced to the maximum extent permissible so as to effect the economic benefits and intent of the parties, and the remainder of this License will continue in full force and effect.  (b) Notwithstanding the foregoing, if applicable law prohibits or restricts You from fully and/or specifically complying with Sections 2 and/or 3 or prevents the enforceability of either of those Sections, this License will immediately terminate and You must immediately discontinue any use of the Covered Code and destroy all copies of it that are in your possession or control.\n\n13.6    Dispute Resolution.  Any litigation or other dispute resolution between You and Apple relating to this License shall take place in the Northern District of California, and You and Apple hereby consent to the personal jurisdiction of, and venue in, the state and federal courts within that District with respect to this License. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded.\n\n13.7    Entire Agreement; Governing Law.  This License constitutes the entire agreement between the parties with respect to the subject matter hereof.  This License shall be governed by the laws of the United States and the State of California, except that body of California law concerning conflicts of law. \n\nWhere You are located in the province of Quebec, Canada, the following clause applies:  The parties hereby confirm that they have requested that this License and all related documents be drafted in English.  Les parties ont exigé que le présent contrat et tous les documents connexes soient rédigés en anglais.\n\nEXHIBIT A. \n\n\"Portions Copyright (c) 1999-2007 Apple Inc.  All Rights Reserved.\n\nThis file contains Original Code and/or Modifications of Original Code as defined in and that are subject to the Apple Public Source License Version 2.0 (the 'License').  You may not use this file except in compliance with the License.  Please obtain a copy of the License at http://www.opensource.apple.com/apsl/ and read it before using this file.\n\nThe Original Code and all software distributed under the License are distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  Please see the License for the specific language governing rights and limitations under the License.\"\n"
  },
  {
    "path": "security-framework/examples/client.rs",
    "content": "use security_framework::secure_transport::ClientBuilder;\nuse std::io::{Read, Write};\nuse std::net::TcpStream;\n\nfn main() {\n    let stream = TcpStream::connect(\"google.com:443\").unwrap();\n    let mut stream = ClientBuilder::new().handshake(\"google.com\", stream).unwrap();\n    println!(\"negotiated chipher: {:?}\", stream.context().negotiated_cipher().unwrap());\n    println!(\"negotiated version: {:?}\", stream.context().negotiated_protocol_version().unwrap());\n\n    stream.write_all(b\"GET / HTTP/1.0\\r\\n\\r\\n\").unwrap();\n    stream.flush().unwrap();\n    let mut buf = vec![];\n    stream.read_to_end(&mut buf).unwrap();\n    println!(\"{}\", String::from_utf8_lossy(&buf));\n}\n"
  },
  {
    "path": "security-framework/examples/find_internet_password.rs",
    "content": "#[cfg(target_os = \"macos\")]\nuse security_framework::os::macos::keychain::SecKeychain;\n#[cfg(target_os = \"macos\")]\nuse security_framework::os::macos::passwords::{SecAuthenticationType, SecProtocolType};\n\nfn main() {\n    #[cfg(target_os = \"macos\")] {\n    let hostname = \"example.com\";\n    let username = \"rusty\";\n    let res = SecKeychain::default().unwrap().find_internet_password(\n        hostname,\n        None,\n        username,\n        \"\",\n        None,\n        SecProtocolType::Any,\n        SecAuthenticationType::Any,\n    );\n    match res {\n        Ok((password, _)) => {\n            println!(\n                \"Password for {}@{} is {} bytes long\",\n                username,\n                hostname,\n                password.len()\n            );\n        }\n        Err(err) if err.code() == -128 => {\n            eprintln!(\"Account was found in the Keychain, but user denied access\");\n        }\n        Err(err) => {\n            eprintln!(\"Password not found. Open Keychain Access.app and add internet password for '{username}' at 'https://{hostname}': {err:?}\");\n        }\n    }\n}}\n"
  },
  {
    "path": "security-framework/examples/set_internet_password.rs",
    "content": "#[cfg(target_os = \"macos\")]\nuse security_framework::os::macos::keychain::SecKeychain;\n#[cfg(target_os = \"macos\")]\nuse security_framework::os::macos::passwords::{SecAuthenticationType, SecProtocolType};\n\nfn main() {\n    #[cfg(target_os = \"macos\")] {\n    let hostname = \"example.com\";\n    let username = \"rusty\";\n    let password = b\"oxidize\";\n\n    let res = SecKeychain::default().unwrap().set_internet_password(\n        hostname,\n        None,\n        username,\n        \"\",\n        None,\n        SecProtocolType::HTTPS,\n        SecAuthenticationType::HTMLForm,\n        password,\n    );\n    match res {\n        Ok(()) => {\n            println!(\n                \"Password set for {username}@{hostname}. You can read it using find_internet_password example\"\n            );\n        }\n        Err(err) => {\n            eprintln!(\"Could not set password: {err:?}\");\n        }\n    }\n}}\n"
  },
  {
    "path": "security-framework/src/access_control.rs",
    "content": "//! Access Control support.\n\nuse crate::base::{Error, Result};\nuse core_foundation::base::{kCFAllocatorDefault, CFOptionFlags, TCFType};\nuse core_foundation::string::CFString;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse security_framework_sys::access_control::{\n    kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,\n    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAttrAccessibleWhenUnlocked,\n    kSecAttrAccessibleWhenUnlockedThisDeviceOnly, SecAccessControlCreateWithFlags,\n    SecAccessControlGetTypeID,\n};\nuse security_framework_sys::base::{errSecParam, SecAccessControlRef};\nuse std::fmt;\nuse std::ptr;\n\ndeclare_TCFType! {\n    /// A type representing sec access control settings.\n    SecAccessControl, SecAccessControlRef\n}\nimpl_TCFType!(\n    SecAccessControl,\n    SecAccessControlRef,\n    SecAccessControlGetTypeID\n);\n\nunsafe impl Sync for SecAccessControl {}\nunsafe impl Send for SecAccessControl {}\n\n/// Specify when an item is available.\npub enum ProtectionMode {\n    /// The data in the keychain can only be accessed when the device is\n    /// unlocked. Only available if a passcode is set on the device.\n    AccessibleWhenPasscodeSetThisDeviceOnly,\n    ///The data in the keychain item can be accessed only while the device is\n    /// unlocked by the user.\n    AccessibleWhenUnlockedThisDeviceOnly,\n    /// The data in the keychain item can be accessed only while the device is\n    /// unlocked by the user.\n    AccessibleWhenUnlocked,\n    /// The data in the keychain item cannot be accessed after a restart until\n    /// the device has been unlocked once by the user.\n    AccessibleAfterFirstUnlockThisDeviceOnly,\n    /// The data in the keychain item cannot be accessed after a restart until\n    /// the device has been unlocked once by the user.\n    AccessibleAfterFirstUnlock,\n}\n\nimpl SecAccessControl {\n    /// Create `AccessControl` object from flags\n    pub fn create_with_flags(flags: CFOptionFlags) -> Result<Self> {\n        Self::create_with_protection(None, flags)\n    }\n\n    /// Create `AccessControl` object from a protection value and flags.\n    pub fn create_with_protection(protection: Option<ProtectionMode>, flags: CFOptionFlags) -> Result<Self> {\n        let protection_val = protection.map(|v| {\n            match v {\n                ProtectionMode::AccessibleWhenPasscodeSetThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly) },\n                ProtectionMode::AccessibleWhenUnlockedThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlockedThisDeviceOnly) },\n                ProtectionMode::AccessibleWhenUnlocked => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlocked) },\n                ProtectionMode::AccessibleAfterFirstUnlockThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly) },\n                ProtectionMode::AccessibleAfterFirstUnlock => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleAfterFirstUnlock) },\n            }\n        }).unwrap_or_else(|| {\n            unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlocked) }\n        });\n        unsafe {\n            let access_control = SecAccessControlCreateWithFlags(\n                kCFAllocatorDefault,\n                protection_val.as_CFTypeRef(),\n                flags,\n                ptr::null_mut(),\n            );\n            if access_control.is_null() {\n                Err(Error::from_code(errSecParam))\n            } else {\n                Ok(Self::wrap_under_create_rule(access_control))\n            }\n        }\n    }\n}\n\nimpl fmt::Debug for SecAccessControl {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"SecAccessControl\").finish_non_exhaustive()\n    }\n}\n"
  },
  {
    "path": "security-framework/src/authorization.rs",
    "content": "//! Authorization Services support.\n\n/// # Potential improvements\n///\n/// * When generic specialization stabilizes prevent copying from `CString` arguments.\n/// * `AuthorizationCopyRightsAsync`\n/// * Provide constants for well known item names\nuse crate::base::{Error, Result};\n#[cfg(all(target_os = \"macos\", feature = \"job-bless\"))]\nuse core_foundation::base::Boolean;\nuse core_foundation::base::{CFTypeRef, TCFType};\nuse core_foundation::bundle::CFBundleRef;\nuse core_foundation::dictionary::{CFDictionary, CFDictionaryRef};\n#[cfg(all(target_os = \"macos\", feature = \"job-bless\"))]\nuse core_foundation::error::CFError;\n#[cfg(all(target_os = \"macos\", feature = \"job-bless\"))]\nuse core_foundation::error::CFErrorRef;\nuse core_foundation::string::{CFString, CFStringRef};\nuse security_framework_sys::authorization as sys;\nuse security_framework_sys::base::errSecConversionError;\nuse std::ffi::{CStr, CString};\nuse std::fs::File;\nuse std::marker::PhantomData;\nuse std::mem::MaybeUninit;\nuse std::os::raw::c_void;\nuse std::ptr::addr_of;\nuse sys::AuthorizationExternalForm;\n\nmacro_rules! optional_str_to_cfref {\n    ($string:ident) => {{\n        $string\n            .map(CFString::new)\n            .map_or(std::ptr::null(), |cfs| cfs.as_concrete_TypeRef())\n    }};\n}\n\nmacro_rules! cstring_or_err {\n    ($x:expr) => {{\n        CString::new($x).map_err(|_| Error::from_code(errSecConversionError))\n    }};\n}\n\nbitflags::bitflags! {\n    /// The flags used to specify authorization options.\n    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n    pub struct Flags: sys::AuthorizationFlags {\n        /// An empty flag set that you use as a placeholder when you don't want\n        /// any of the other flags.\n        const DEFAULTS = sys::kAuthorizationFlagDefaults;\n\n        /// A flag that permits user interaction as needed.\n        const INTERACTION_ALLOWED = sys::kAuthorizationFlagInteractionAllowed;\n\n        /// A flag that permits the Security Server to attempt to grant the\n        /// rights requested.\n        const EXTEND_RIGHTS = sys::kAuthorizationFlagExtendRights;\n\n        /// A flag that permits the Security Server to grant rights on an\n        /// individual basis.\n        const PARTIAL_RIGHTS = sys::kAuthorizationFlagPartialRights;\n\n        /// A flag that instructs the Security Server to revoke authorization.\n        const DESTROY_RIGHTS = sys::kAuthorizationFlagDestroyRights;\n\n        /// A flag that instructs the Security Server to preauthorize the rights\n        /// requested.\n        const PREAUTHORIZE = sys::kAuthorizationFlagPreAuthorize;\n    }\n}\n\nimpl Default for Flags {\n    #[inline(always)]\n    fn default() -> Self {\n        Self::DEFAULTS\n    }\n}\n\n/// Information about an authorization right or the environment.\n#[repr(C)]\npub struct AuthorizationItem(sys::AuthorizationItem);\n\nimpl AuthorizationItem {\n    /// The required name of the authorization right or environment data.\n    ///\n    /// If `name` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    #[must_use]\n    pub fn name(&self) -> &str {\n        unsafe {\n            CStr::from_ptr(self.0.name)\n                .to_str()\n                .expect(\"AuthorizationItem::name failed to convert &str to CStr\")\n        }\n    }\n\n    /// The information pertaining to the name field. Do not rely on NULL\n    /// termination of string data.\n    #[inline]\n    #[must_use]\n    pub fn value(&self) -> Option<&[u8]> {\n        if self.0.value.is_null() {\n            return None;\n        }\n\n        let value = unsafe { std::slice::from_raw_parts(self.0.value as *const u8, self.0.valueLength) };\n\n        Some(value)\n    }\n}\n\n/// A set of authorization items returned and owned by the Security Server.\n#[derive(Debug)]\n#[repr(C)]\npub struct AuthorizationItemSet<'a> {\n    inner: *const sys::AuthorizationItemSet,\n    phantom: PhantomData<&'a sys::AuthorizationItemSet>,\n}\n\nimpl Drop for AuthorizationItemSet<'_> {\n    #[inline]\n    fn drop(&mut self) {\n        unsafe {\n            sys::AuthorizationFreeItemSet(self.inner.cast_mut());\n        }\n    }\n}\n\n/// Used by `AuthorizationItemSetBuilder` to store data pointed to by\n/// `sys::AuthorizationItemSet`.\n#[derive(Debug)]\npub struct AuthorizationItemSetStorage {\n    /// The layout of this is a little awkward because of the requirements of\n    /// Apple's APIs. `items` contains pointers to data owned by `names` and\n    /// `values`, so we must not modify them once `items` has been set up.\n    names: Vec<CString>,\n    values: Vec<Option<Vec<u8>>>,\n    items: Vec<sys::AuthorizationItem>,\n\n    /// Must not be given to APIs which would attempt to modify it.\n    ///\n    /// See `AuthorizationItemSet` for sets owned by the Security Server which\n    /// are writable.\n    pub set: sys::AuthorizationItemSet,\n}\n\nimpl Default for AuthorizationItemSetStorage {\n    #[inline]\n    fn default() -> Self {\n        Self {\n            names: Vec::new(),\n            values: Vec::new(),\n            items: Vec::new(),\n            set: sys::AuthorizationItemSet {\n                count: 0,\n                items: std::ptr::null_mut(),\n            },\n        }\n    }\n}\n\n/// A convenience `AuthorizationItemSetBuilder` builder which enabled you to use\n/// rust types. All names and values passed in will be copied.\n#[derive(Debug, Default)]\npub struct AuthorizationItemSetBuilder {\n    storage: AuthorizationItemSetStorage,\n}\n\n// Stores AuthorizationItems contiguously, and their items separately\nimpl AuthorizationItemSetBuilder {\n    /// Creates a new `AuthorizationItemSetStore`, which simplifies creating\n    /// owned vectors of `AuthorizationItem`s.\n    #[inline(always)]\n    #[must_use]\n    pub fn new() -> Self {\n        Default::default()\n    }\n\n    /// Adds an `AuthorizationItem` with the name set to a right and an empty\n    /// value.\n    ///\n    /// If `name` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    pub fn add_right<N: Into<Vec<u8>>>(mut self, name: N) -> Result<Self> {\n        self.storage.names.push(cstring_or_err!(name)?);\n        self.storage.values.push(None);\n        Ok(self)\n    }\n\n    /// Adds an `AuthorizationItem` with arbitrary data.\n    ///\n    /// If `name` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    pub fn add_data<N, V>(mut self, name: N, value: V) -> Result<Self>\n    where\n        N: Into<Vec<u8>>,\n        V: Into<Vec<u8>>,\n    {\n        self.storage.names.push(cstring_or_err!(name)?);\n        self.storage.values.push(Some(value.into()));\n        Ok(self)\n    }\n\n    /// Adds an `AuthorizationItem` with NULL terminated string data.\n    ///\n    /// If `name` or `value` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    pub fn add_string<N, V>(mut self, name: N, value: V) -> Result<Self>\n    where\n        N: Into<Vec<u8>>,\n        V: Into<Vec<u8>>,\n    {\n        self.storage.names.push(cstring_or_err!(name)?);\n        self.storage\n            .values\n            .push(Some(cstring_or_err!(value)?.to_bytes().to_vec()));\n        Ok(self)\n    }\n\n    /// Creates the `sys::AuthorizationItemSet`, and gives you ownership of the\n    /// data it points to.\n    #[must_use]\n    pub fn build(mut self) -> AuthorizationItemSetStorage {\n        self.storage.items = self\n            .storage\n            .names\n            .iter()\n            .zip(self.storage.values.iter())\n            .map(|(n, v)| sys::AuthorizationItem {\n                name: n.as_ptr(),\n                value: v\n                    .as_ref()\n                    .map_or(std::ptr::null_mut(), |v| v.as_ptr() as *mut c_void),\n                valueLength: v.as_ref().map_or(0, |v| v.len()),\n                flags: 0,\n            })\n            .collect();\n\n        self.storage.set = sys::AuthorizationItemSet {\n            count: self.storage.items.len() as u32,\n            items: self.storage.items.as_ptr().cast_mut(),\n        };\n\n        self.storage\n    }\n}\n\n/// Used by `Authorization::set_item` to define the rules of he right.\n#[derive(Copy, Clone)]\npub enum RightDefinition<'a> {\n    /// The dictionary will contain the keys and values that define the rules.\n    FromDictionary(&'a CFDictionary<CFStringRef, CFTypeRef>),\n\n    /// The specified right's rules will be duplicated.\n    FromExistingRight(&'a str),\n}\n\n/// A wrapper around `AuthorizationCreate` and functions which operate on an\n/// `AuthorizationRef`.\n#[derive(Debug)]\npub struct Authorization {\n    handle: sys::AuthorizationRef,\n    free_flags: Flags,\n}\n\nimpl TryFrom<AuthorizationExternalForm> for Authorization {\n    type Error = Error;\n\n    /// Internalizes the external representation of an authorization reference.\n    #[cold]\n    fn try_from(external_form: AuthorizationExternalForm) -> Result<Self> {\n        let mut handle = MaybeUninit::<sys::AuthorizationRef>::uninit();\n\n        let status = unsafe {\n            sys::AuthorizationCreateFromExternalForm(&external_form, handle.as_mut_ptr())\n        };\n\n        if status != sys::errAuthorizationSuccess {\n            return Err(Error::from_code(status));\n        }\n\n        let auth = Self {\n            handle: unsafe { handle.assume_init() },\n            free_flags: Flags::default(),\n        };\n\n        Ok(auth)\n    }\n}\n\nimpl Authorization {\n    /// Creates an authorization object which has no environment or associated\n    /// rights.\n    #[inline]\n    #[allow(clippy::should_implement_trait)]\n    pub fn default() -> Result<Self> {\n        Self::new(None, None, Default::default())\n    }\n\n    /// Creates an authorization reference and provides an option to authorize\n    /// or preauthorize rights.\n    ///\n    /// `rights` should be the names of the rights you want to create.\n    ///\n    /// `environment` is used when authorizing or preauthorizing rights. Not\n    /// used in OS X v10.2 and earlier. In macOS 10.3 and later, you can pass\n    /// icon or prompt data to be used in the authentication dialog box. In\n    /// macOS 10.4 and later, you can also pass a user name and password in\n    /// order to authorize a user without user interaction.\n    #[allow(clippy::unnecessary_cast)]\n    #[allow(clippy::needless_pass_by_value)]\n    pub fn new(\n        // FIXME: this should have been by reference\n        rights: Option<AuthorizationItemSetStorage>,\n        environment: Option<AuthorizationItemSetStorage>,\n        flags: Flags,\n    ) -> Result<Self> {\n        let rights_ptr = rights.as_ref().map_or(std::ptr::null(), |r| {\n            addr_of!(r.set).cast::<sys::AuthorizationItemSet>()\n        });\n\n        let env_ptr = environment.as_ref().map_or(std::ptr::null(), |e| {\n            addr_of!(e.set).cast::<sys::AuthorizationItemSet>()\n        });\n\n        let mut handle = MaybeUninit::<sys::AuthorizationRef>::uninit();\n\n        let status = unsafe {\n            sys::AuthorizationCreate(rights_ptr, env_ptr, flags.bits(), handle.as_mut_ptr())\n        };\n\n        if status != sys::errAuthorizationSuccess {\n            return Err(Error::from_code(status));\n        }\n\n        Ok(Self {\n            handle: unsafe { handle.assume_init() },\n            free_flags: Default::default(),\n        })\n    }\n\n    /// Internalizes the external representation of an authorization reference.\n    #[deprecated(since = \"2.0.1\", note = \"Please use the TryFrom trait instead\")]\n    pub fn from_external_form(external_form: sys::AuthorizationExternalForm) -> Result<Self> {\n        external_form.try_into()\n    }\n\n    /// By default the rights acquired will be retained by the Security Server.\n    /// Use this to ensure they are destroyed and to prevent shared rights'\n    /// continued used by other processes.\n    #[inline(always)]\n    pub fn destroy_rights(mut self) {\n        self.free_flags = Flags::DESTROY_RIGHTS;\n    }\n\n    /// Retrieve's the right's definition as a dictionary. Use `right_exists`\n    /// if you want to avoid retrieving the dictionary.\n    ///\n    /// `name` can be a wildcard right name.\n    ///\n    /// If `name` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    // TODO: deprecate and remove. CFDictionary should not be exposed in public Rust APIs.\n    pub fn get_right<T: Into<Vec<u8>>>(name: T) -> Result<CFDictionary<CFString, CFTypeRef>> {\n        let name = cstring_or_err!(name)?;\n        let mut dict = MaybeUninit::<CFDictionaryRef>::uninit();\n\n        let status = unsafe { sys::AuthorizationRightGet(name.as_ptr(), dict.as_mut_ptr()) };\n\n        if status != sys::errAuthorizationSuccess {\n            return Err(Error::from_code(status));\n        }\n\n        let dict = unsafe { CFDictionary::wrap_under_create_rule(dict.assume_init()) };\n\n        Ok(dict)\n    }\n\n    /// Checks if a right exists within the policy database. This is the same as\n    /// `get_right`, but avoids a dictionary allocation.\n    ///\n    /// If `name` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    pub fn right_exists<T: Into<Vec<u8>>>(name: T) -> Result<bool> {\n        let name = cstring_or_err!(name)?;\n\n        let status = unsafe { sys::AuthorizationRightGet(name.as_ptr(), std::ptr::null_mut()) };\n\n        Ok(status == sys::errAuthorizationSuccess)\n    }\n\n    /// Removes a right from the policy database.\n    ///\n    /// `name` cannot be a wildcard right name.\n    ///\n    /// If `name` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    pub fn remove_right<T: Into<Vec<u8>>>(&self, name: T) -> Result<()> {\n        let name = cstring_or_err!(name)?;\n\n        let status = unsafe { sys::AuthorizationRightRemove(self.handle, name.as_ptr()) };\n\n        if status != sys::errAuthorizationSuccess {\n            return Err(Error::from_code(status));\n        }\n\n        Ok(())\n    }\n\n    /// Creates or updates a right entry in the policy database. Your process\n    /// must have a code signature in order to be able to add rights to the\n    /// authorization database.\n    ///\n    /// `name` cannot be a wildcard right.\n    ///\n    /// `definition` can be either a `CFDictionaryRef` containing keys defining\n    /// the rules or a `CFStringRef` representing the name of another right\n    /// whose rules you wish to duplicaate.\n    ///\n    /// `description` is a key which can be used to look up localized\n    /// descriptions.\n    ///\n    /// `bundle` will be used to get localizations from if not the main bundle.\n    ///\n    /// `localeTableName` will be used to get localizations if provided.\n    ///\n    /// If `name` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    pub fn set_right<T: Into<Vec<u8>>>(\n        &self,\n        name: T,\n        definition: RightDefinition<'_>,\n        description: Option<&str>,\n        bundle: Option<CFBundleRef>,\n        locale: Option<&str>,\n    ) -> Result<()> {\n        let name = cstring_or_err!(name)?;\n\n        let definition_cfstring: CFString;\n        let definition_ref = match definition {\n            RightDefinition::FromDictionary(def) => def.as_CFTypeRef(),\n            RightDefinition::FromExistingRight(def) => {\n                definition_cfstring = CFString::new(def);\n                definition_cfstring.as_CFTypeRef()\n            },\n        };\n\n        let status = unsafe {\n            sys::AuthorizationRightSet(\n                self.handle,\n                name.as_ptr(),\n                definition_ref,\n                optional_str_to_cfref!(description),\n                bundle.unwrap_or(std::ptr::null_mut()),\n                optional_str_to_cfref!(locale),\n            )\n        };\n\n        if status != sys::errAuthorizationSuccess {\n            return Err(Error::from_code(status));\n        }\n\n        Ok(())\n    }\n\n    /// An authorization plugin can store the results of an authentication\n    /// operation by calling the `SetContextValue` function. You can then\n    /// retrieve this supporting data, such as the user name.\n    ///\n    /// `tag` should specify the type of data the Security Server should return.\n    /// If `None`, all available information is retreieved.\n    ///\n    /// If `tag` isn't convertable to a `CString` it will return\n    /// Err(errSecConversionError).\n    pub fn copy_info<T: Into<Vec<u8>>>(&self, tag: Option<T>) -> Result<AuthorizationItemSet<'_>> {\n        let tag_with_nul: CString;\n\n        let tag_ptr = match tag {\n            Some(tag) => {\n                tag_with_nul = cstring_or_err!(tag)?;\n                tag_with_nul.as_ptr()\n            },\n            None => std::ptr::null(),\n        };\n\n        let mut inner = MaybeUninit::<*mut sys::AuthorizationItemSet>::uninit();\n\n        let status = unsafe { sys::AuthorizationCopyInfo(self.handle, tag_ptr, inner.as_mut_ptr()) };\n\n        if status != sys::errAuthorizationSuccess {\n            return Err(Error::from(status));\n        }\n\n        let set = AuthorizationItemSet {\n            inner: unsafe { inner.assume_init() },\n            phantom: PhantomData,\n        };\n\n        Ok(set)\n    }\n\n    /// Creates an external representation of an authorization reference so that\n    /// you can transmit it between processes.\n    pub fn make_external_form(&self) -> Result<sys::AuthorizationExternalForm> {\n        let mut external_form = MaybeUninit::<sys::AuthorizationExternalForm>::uninit();\n\n        let status = unsafe { sys::AuthorizationMakeExternalForm(self.handle, external_form.as_mut_ptr()) };\n\n        if status != sys::errAuthorizationSuccess {\n            return Err(Error::from(status));\n        }\n\n        Ok(unsafe { external_form.assume_init() })\n    }\n\n    /// Runs an executable tool with root privileges.\n    /// Discards executable's output\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    pub fn execute_with_privileges<P, S, I>(\n        &self,\n        command: P,\n        arguments: I,\n        flags: Flags,\n    ) -> Result<()>\n    where\n        P: AsRef<std::path::Path>,\n        I: IntoIterator<Item = S>,\n        S: AsRef<std::ffi::OsStr>,\n    {\n        use std::os::unix::ffi::OsStrExt;\n\n        let arguments = arguments\n            .into_iter().flat_map(|a| CString::new(a.as_ref().as_bytes()))\n            .collect::<Vec<_>>();\n        self.execute_with_privileges_internal(command.as_ref().as_os_str().as_bytes(), &arguments, flags, false)?;\n        Ok(())\n    }\n\n    /// Runs an executable tool with root privileges,\n    /// and returns a `File` handle to its communication pipe\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    pub fn execute_with_privileges_piped<P, S, I>(\n        &self,\n        command: P,\n        arguments: I,\n        flags: Flags,\n    ) -> Result<File>\n    where\n        P: AsRef<std::path::Path>,\n        I: IntoIterator<Item = S>,\n        S: AsRef<std::ffi::OsStr>,\n    {\n        use std::os::unix::ffi::OsStrExt;\n\n        let arguments = arguments\n            .into_iter().flat_map(|a| CString::new(a.as_ref().as_bytes()))\n            .collect::<Vec<_>>();\n        Ok(self.execute_with_privileges_internal(command.as_ref().as_os_str().as_bytes(), &arguments, flags, true)?.unwrap())\n    }\n\n    /// Submits the executable for the given label as a `launchd` job.\n    #[cfg(all(target_os = \"macos\", feature = \"job-bless\"))]\n    pub fn job_bless(&self, label: &str) -> Result<(), CFError> {\n        #[link(name = \"ServiceManagement\", kind = \"framework\")]\n        unsafe extern \"C\" {\n            static kSMDomainSystemLaunchd: CFStringRef;\n\n            fn SMJobBless(\n                domain: CFStringRef,\n                executableLabel: CFStringRef,\n                auth: sys::AuthorizationRef,\n                error: *mut CFErrorRef,\n            ) -> Boolean;\n        }\n\n        unsafe {\n            let mut error = std::ptr::null_mut();\n            SMJobBless(\n                kSMDomainSystemLaunchd,\n                CFString::new(label).as_concrete_TypeRef(),\n                self.handle,\n                &mut error,\n            );\n            if !error.is_null() {\n                return Err(CFError::wrap_under_create_rule(error));\n            }\n\n            Ok(())\n        }\n    }\n\n    // Runs an executable tool with root privileges.\n    #[cfg(target_os = \"macos\")]\n    fn execute_with_privileges_internal(\n        &self,\n        command: &[u8],\n        arguments: &[CString],\n        flags: Flags,\n        make_pipe: bool,\n    ) -> Result<Option<File>> {\n        use std::os::unix::io::{FromRawFd, RawFd};\n\n        let c_cmd = cstring_or_err!(command)?;\n\n        let mut c_args = arguments.iter().map(|a| a.as_ptr().cast_mut()).collect::<Vec<_>>();\n        c_args.push(std::ptr::null_mut());\n\n        let mut pipe: *mut libc::FILE = std::ptr::null_mut();\n\n        let status = unsafe {\n            sys::AuthorizationExecuteWithPrivileges(\n                self.handle,\n                c_cmd.as_ptr(),\n                flags.bits(),\n                c_args.as_ptr(),\n                if make_pipe { &mut pipe } else { std::ptr::null_mut() },\n            )\n        };\n\n        crate::cvt(status)?;\n        Ok(if make_pipe {\n            if pipe.is_null() {\n                return Err(Error::from_code(32)); // EPIPE?\n            }\n            Some(unsafe { File::from_raw_fd(libc::fileno(pipe) as RawFd) })\n        } else {\n            None\n        })\n    }\n}\n\nimpl Drop for Authorization {\n    #[inline]\n    fn drop(&mut self) {\n        unsafe {\n            sys::AuthorizationFree(self.handle, self.free_flags.bits());\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_create_default_authorization() {\n        Authorization::default().unwrap();\n    }\n\n    #[test]\n    fn test_create_allowed_authorization() -> Result<()> {\n        let rights = AuthorizationItemSetBuilder::new()\n            .add_right(\"system.hdd.smart\")?\n            .add_right(\"system.login.done\")?\n            .build();\n\n        Authorization::new(Some(rights), None, Flags::EXTEND_RIGHTS).unwrap();\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_create_then_destroy_allowed_authorization() -> Result<()> {\n        let rights = AuthorizationItemSetBuilder::new()\n            .add_right(\"system.hdd.smart\")?\n            .add_right(\"system.login.done\")?\n            .build();\n\n        let auth = Authorization::new(Some(rights), None, Flags::EXTEND_RIGHTS).unwrap();\n        auth.destroy_rights();\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_create_authorization_requiring_interaction() -> Result<()> {\n        let rights = AuthorizationItemSetBuilder::new()\n            .add_right(\"system.privilege.admin\")?\n            .build();\n\n        let error = Authorization::new(Some(rights), None, Flags::EXTEND_RIGHTS).unwrap_err();\n\n        assert_eq!(error.code(), sys::errAuthorizationInteractionNotAllowed);\n\n        Ok(())\n    }\n\n    fn create_credentials_env() -> Result<AuthorizationItemSetStorage> {\n        let set = AuthorizationItemSetBuilder::new()\n            .add_string(\"username\", std::env::var(\"USER\").expect(\"You must set the USER environment variable\"))?\n            .add_string(\"password\", std::env::var(\"PASSWORD\").expect(\"You must set the PASSWORD environment varible\"))?\n            .build();\n\n        Ok(set)\n    }\n\n    #[test]\n    fn test_create_authorization_with_bad_credentials() -> Result<()> {\n        let rights = AuthorizationItemSetBuilder::new()\n            .add_right(\"system.privilege.admin\")?\n            .build();\n\n        let env = AuthorizationItemSetBuilder::new()\n            .add_string(\"username\", \"Tim Apple\")?\n            .add_string(\"password\", \"butterfly\")?\n            .build();\n\n        let error =\n            Authorization::new(Some(rights), Some(env), Flags::INTERACTION_ALLOWED).unwrap_err();\n\n        assert_eq!(error.code(), sys::errAuthorizationDenied);\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_create_authorization_with_credentials() -> Result<()> {\n        if std::env::var_os(\"PASSWORD\").is_none() {\n            return Ok(());\n        }\n\n        let rights = AuthorizationItemSetBuilder::new()\n            .add_right(\"system.privilege.admin\")?\n            .build();\n\n        let env = create_credentials_env()?;\n\n        Authorization::new(Some(rights), Some(env), Flags::EXTEND_RIGHTS).unwrap();\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_query_authorization_database() -> Result<()> {\n        assert!(Authorization::right_exists(\"system.hdd.smart\")?);\n        assert!(!Authorization::right_exists(\"EMPTY\")?);\n\n        let dict = Authorization::get_right(\"system.hdd.smart\").unwrap();\n\n        let key = CFString::from_static_string(\"class\");\n        assert!(dict.contains_key(&key));\n\n        let invalid_key = CFString::from_static_string(\"EMPTY\");\n        assert!(!dict.contains_key(&invalid_key));\n\n        Ok(())\n    }\n\n    /// This test will only pass if its process has a valid code signature.\n    #[test]\n    fn test_modify_authorization_database() -> Result<()> {\n        if std::env::var_os(\"PASSWORD\").is_none() {\n            return Ok(());\n        }\n\n        let rights = AuthorizationItemSetBuilder::new()\n            .add_right(\"config.modify.\")?\n            .build();\n\n        let env = create_credentials_env()?;\n\n        let auth = Authorization::new(Some(rights), Some(env), Flags::EXTEND_RIGHTS).unwrap();\n\n        assert!(!Authorization::right_exists(\"TEST_RIGHT\")?);\n\n        auth.set_right(\n            \"TEST_RIGHT\",\n            RightDefinition::FromExistingRight(\"system.hdd.smart\"),\n            None,\n            None,\n            None,\n        )\n        .unwrap();\n\n        assert!(Authorization::right_exists(\"TEST_RIGHT\")?);\n\n        auth.remove_right(\"TEST_RIGHT\").unwrap();\n\n        assert!(!Authorization::right_exists(\"TEST_RIGHT\")?);\n\n        Ok(())\n    }\n\n    /// This test will succeed if authorization popup is approved.\n    #[test]\n    fn test_execute_with_privileges() -> Result<()> {\n        if std::env::var_os(\"PASSWORD\").is_none() {\n            return Ok(());\n        }\n\n        let rights = AuthorizationItemSetBuilder::new()\n            .add_right(\"system.privilege.admin\")?\n            .build();\n\n        let auth = Authorization::new(\n            Some(rights),\n            None,\n            Flags::DEFAULTS\n                | Flags::INTERACTION_ALLOWED\n                | Flags::PREAUTHORIZE\n                | Flags::EXTEND_RIGHTS,\n        )?;\n\n        let file = auth.execute_with_privileges_piped(\"/bin/ls\", [\"/\"], Flags::DEFAULTS)?;\n\n        use std::io::{self, BufRead};\n        for line in io::BufReader::new(file).lines() {\n            let _ = line.unwrap();\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "security-framework/src/base.rs",
    "content": "//! Support types for other modules.\n\nuse core_foundation::string::CFString;\nuse core_foundation_sys::base::OSStatus;\nuse std::num::NonZeroI32;\nuse std::{error, fmt, result};\n\n/// A `Result` type commonly returned by functions.\npub type Result<T, E = Error> = result::Result<T, E>;\n\n/// A Security Framework error.\n#[derive(Copy, Clone)]\npub struct Error(NonZeroI32);\n\nimpl fmt::Debug for Error {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let mut builder = fmt.debug_struct(\"Error\");\n        builder.field(\"code\", &self.0);\n        if let Some(message) = self.message() {\n            builder.field(\"message\", &message);\n        }\n        builder.finish()\n    }\n}\n\nimpl Error {\n    /// Creates a new `Error` from a status code.\n    /// The code must not be zero\n    #[inline]\n    #[must_use]\n    pub fn from_code(code: OSStatus) -> Self {\n        Self(NonZeroI32::new(code).unwrap_or_else(|| NonZeroI32::new(1).unwrap()))\n    }\n\n    /// Returns a string describing the current error, if available.\n    #[inline(always)]\n    #[must_use]\n    pub fn message(self) -> Option<String> {\n        self.inner_message()\n    }\n\n    #[cold]\n    fn inner_message(self) -> Option<String> {\n        use core_foundation::base::TCFType;\n        use security_framework_sys::base::SecCopyErrorMessageString;\n        use std::ptr;\n\n        unsafe {\n            let s = SecCopyErrorMessageString(self.code(), ptr::null_mut());\n            if s.is_null() {\n                None\n            } else {\n                Some(CFString::wrap_under_create_rule(s).to_string())\n            }\n        }\n    }\n\n    /// Returns the code of the current error.\n    #[inline(always)]\n    #[must_use]\n    pub const fn code(self) -> OSStatus {\n        self.0.get() as _\n    }\n}\n\nimpl From<OSStatus> for Error {\n    #[inline(always)]\n    fn from(code: OSStatus) -> Self {\n        Self::from_code(code)\n    }\n}\n\nimpl fmt::Display for Error {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(message) = self.message() {\n            write!(fmt, \"{message}\")\n        } else {\n            write!(fmt, \"error code {}\", self.code())\n        }\n    }\n}\n\nimpl error::Error for Error {}\n"
  },
  {
    "path": "security-framework/src/certificate.rs",
    "content": "//! Certificate support.\nuse core_foundation::array::{CFArray, CFArrayRef};\nuse core_foundation::base::{TCFType, ToVoid};\nuse core_foundation::data::CFData;\nuse core_foundation::dictionary::CFMutableDictionary;\nuse core_foundation::string::CFString;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse core_foundation_sys::base::kCFAllocatorDefault;\n#[cfg(any(target_os = \"ios\", target_os = \"tvos\", target_os = \"watchos\", target_os = \"visionos\"))]\nuse security_framework_sys::base::{errSecNotTrusted, errSecSuccess};\nuse security_framework_sys::base::{errSecParam, SecCertificateRef};\nuse security_framework_sys::certificate::*;\nuse security_framework_sys::keychain_item::SecItemDelete;\nuse std::fmt;\nuse std::ptr;\n\nuse crate::base::{Error, Result};\nuse crate::cvt;\nuse crate::key;\n#[cfg(target_os = \"macos\")]\nuse crate::os::macos::keychain::SecKeychain;\nuse core_foundation::base::FromVoid;\nuse core_foundation::error::{CFError, CFErrorRef};\nuse core_foundation::number::CFNumber;\nuse security_framework_sys::item::kSecValueRef;\n\ndeclare_TCFType! {\n    /// A type representing a certificate.\n    SecCertificate, SecCertificateRef\n}\nimpl_TCFType!(SecCertificate, SecCertificateRef, SecCertificateGetTypeID);\n\nunsafe impl Sync for SecCertificate {}\nunsafe impl Send for SecCertificate {}\n\nimpl fmt::Debug for SecCertificate {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"SecCertificate\")\n            .field(\"subject\", &self.subject_summary())\n            .finish()\n    }\n}\n\nimpl SecCertificate {\n    /// Creates a `SecCertificate` from DER encoded certificate data.\n    pub fn from_der(der_data: &[u8]) -> Result<Self> {\n        let der_data = CFData::from_buffer(der_data);\n        unsafe {\n            let certificate = SecCertificateCreateWithData(kCFAllocatorDefault, der_data.as_concrete_TypeRef());\n            if certificate.is_null() {\n                Err(Error::from_code(errSecParam))\n            } else {\n                Ok(Self::wrap_under_create_rule(certificate))\n            }\n        }\n    }\n\n    /// Returns DER encoded data describing this certificate.\n    #[must_use]\n    pub fn to_der(&self) -> Vec<u8> {\n        unsafe {\n            let der_data = SecCertificateCopyData(self.0);\n            CFData::wrap_under_create_rule(der_data).to_vec()\n        }\n    }\n\n    /// Adds a certificate to a keychain.\n    #[cfg(target_os = \"macos\")]\n    pub fn add_to_keychain(&self, keychain: Option<SecKeychain>) -> Result<()> {\n        let kch = match keychain {\n            Some(kch) => kch,\n            _ => SecKeychain::default()?,\n        };\n        cvt(unsafe {\n            SecCertificateAddToKeychain(self.as_CFTypeRef() as *mut _, kch.as_CFTypeRef() as *mut _)\n        })\n    }\n\n    /// Returns a human readable summary of this certificate.\n    #[must_use]\n    pub fn subject_summary(&self) -> String {\n        unsafe {\n            let summary = SecCertificateCopySubjectSummary(self.0);\n            CFString::wrap_under_create_rule(summary).to_string()\n        }\n    }\n\n    /// Returns a vector of email addresses for the subject of the certificate.\n    pub fn email_addresses(&self) -> Result<Vec<String>, Error> {\n        let mut array: CFArrayRef = ptr::null();\n        unsafe {\n            cvt(SecCertificateCopyEmailAddresses(\n                self.as_concrete_TypeRef(),\n                &mut array,\n            ))?;\n\n            let array = CFArray::<CFString>::wrap_under_create_rule(array);\n            Ok(array.into_iter().map(|p| p.to_string()).collect())\n        }\n    }\n\n    /// Returns DER encoded X.509 distinguished name of the certificate issuer.\n    #[must_use]\n    pub fn issuer(&self) -> Vec<u8> {\n        unsafe {\n            let issuer = SecCertificateCopyNormalizedIssuerSequence(self.0);\n            CFData::wrap_under_create_rule(issuer).to_vec()\n        }\n    }\n\n    /// Returns DER encoded X.509 distinguished name of the certificate subject.\n    #[must_use]\n    pub fn subject(&self) -> Vec<u8> {\n        unsafe {\n            let subject = SecCertificateCopyNormalizedSubjectSequence(self.0);\n            CFData::wrap_under_create_rule(subject).to_vec()\n        }\n    }\n\n    /// Returns DER encoded serial number of the certificate.\n    pub fn serial_number_bytes(&self) -> Result<Vec<u8>, CFError> {\n        unsafe {\n            let mut error: CFErrorRef = ptr::null_mut();\n            let serial_number = SecCertificateCopySerialNumberData(self.0, &mut error);\n            if error.is_null() {\n                Ok(CFData::wrap_under_create_rule(serial_number).to_vec())\n            } else {\n                Err(CFError::wrap_under_create_rule(error))\n            }\n        }\n    }\n\n    /// Returns DER encoded subjectPublicKeyInfo of certificate if available. This can be used\n    /// for certificate pinning.\n    pub fn public_key_info_der(&self) -> Result<Option<Vec<u8>>> {\n        // Imported from TrustKit\n        // https://github.com/datatheorem/TrustKit/blob/master/TrustKit/Pinning/TSKSPKIHashCache.m\n        let public_key = self.public_key()?;\n        Ok(self.pk_to_der(public_key))\n    }\n\n    #[must_use]\n    #[allow(clippy::unused_self)]\n    #[allow(clippy::needless_pass_by_value)]\n    fn pk_to_der(&self, public_key: key::SecKey) -> Option<Vec<u8>> {\n        use security_framework_sys::item::{kSecAttrKeySizeInBits, kSecAttrKeyType};\n\n        let public_key_attributes = public_key.attributes();\n        let public_key_type = public_key_attributes\n            .find(unsafe { kSecAttrKeyType }.cast::<std::os::raw::c_void>())?;\n        let public_keysize = public_key_attributes\n            .find(unsafe { kSecAttrKeySizeInBits }.cast::<std::os::raw::c_void>())?;\n        let public_keysize = unsafe { CFNumber::from_void(*public_keysize) };\n        let public_keysize_val = public_keysize.to_i64()? as u32;\n        let hdr_bytes = get_asn1_header_bytes(\n            unsafe { CFString::wrap_under_get_rule((*public_key_type).cast()) },\n            public_keysize_val,\n        )?;\n        let public_key_data = public_key.external_representation()?;\n        let mut out = Vec::with_capacity(hdr_bytes.len() + public_key_data.len() as usize);\n        out.extend_from_slice(hdr_bytes);\n        out.extend_from_slice(public_key_data.bytes());\n        Some(out)\n    }\n\n    /// Get public key from certificate\n    pub fn public_key(&self) -> Result<key::SecKey> {\n        use crate::policy::SecPolicy;\n        use crate::trust::SecTrust;\n        use std::slice::from_ref;\n\n        let policy = SecPolicy::create_x509();\n        let mut trust = SecTrust::create_with_certificates(from_ref(self), from_ref(&policy))?;\n        #[allow(deprecated)]\n        #[cfg(not(any(target_os = \"ios\", target_os = \"tvos\", target_os = \"watchos\", target_os = \"visionos\")))]\n        trust.evaluate()?;\n        #[cfg(any(target_os = \"ios\", target_os = \"tvos\", target_os = \"watchos\", target_os = \"visionos\"))]\n        cvt(match trust.evaluate_with_error() {\n            Ok(_) => errSecSuccess,\n            Err(_) => errSecNotTrusted,\n        })?;\n        trust.copy_public_key()\n    }\n\n    /// Translates to `SecItemDelete`, passing in the `SecCertificateRef`\n    pub fn delete(&self) -> Result<(), Error> {\n        let query = CFMutableDictionary::from_CFType_pairs(&[(\n            unsafe { kSecValueRef }.to_void(),\n            self.to_void(),\n        )]);\n\n        cvt(unsafe { SecItemDelete(query.as_concrete_TypeRef()) })\n    }\n}\n\nfn get_asn1_header_bytes(pkt: CFString, ksz: u32) -> Option<&'static [u8]> {\n    use security_framework_sys::item::{kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyTypeRSA};\n\n    if pkt == unsafe { CFString::wrap_under_get_rule(kSecAttrKeyTypeRSA) } && ksz == 2048 {\n        return Some(&RSA_2048_ASN1_HEADER);\n    }\n    if pkt == unsafe { CFString::wrap_under_get_rule(kSecAttrKeyTypeRSA) } && ksz == 4096 {\n        return Some(&RSA_4096_ASN1_HEADER);\n    }\n    if pkt == unsafe { CFString::wrap_under_get_rule(kSecAttrKeyTypeECSECPrimeRandom) } && ksz == 256 {\n        return Some(&EC_DSA_SECP_256_R1_ASN1_HEADER);\n    }\n    if pkt == unsafe { CFString::wrap_under_get_rule(kSecAttrKeyTypeECSECPrimeRandom) } && ksz == 384 {\n        return Some(&EC_DSA_SECP_384_R1_ASN1_HEADER);\n    }\n    None\n}\n\nconst RSA_2048_ASN1_HEADER: [u8; 24] = [\n    0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,\n    0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,\n];\n\nconst RSA_4096_ASN1_HEADER: [u8; 24] = [\n    0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,\n    0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00,\n];\n\nconst EC_DSA_SECP_256_R1_ASN1_HEADER: [u8; 26] = [\n    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,\n    0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,\n];\n\nconst EC_DSA_SECP_384_R1_ASN1_HEADER: [u8; 23] = [\n    0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b,\n    0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00,\n];\n\n#[cfg(test)]\nmod test {\n    use crate::test::certificate;\n    use x509_parser::prelude::*;\n\n    #[test]\n    fn subject_summary() {\n        let cert = certificate();\n        assert_eq!(\"foobar.com\", cert.subject_summary());\n    }\n\n    #[test]\n    fn email_addresses() {\n        let cert = certificate();\n        assert_eq!(Vec::<String>::new(), cert.email_addresses().unwrap());\n    }\n\n    #[test]\n    fn issuer() {\n        let cert = certificate();\n        let issuer = cert.issuer();\n        let (_, name) = X509Name::from_der(&issuer).unwrap();\n        let name_str = name.to_string_with_registry(oid_registry()).unwrap();\n        assert_eq!(\n            \"C=US, ST=California, L=Palo Alto, O=Foobar LLC, OU=Dev Land, CN=foobar.com\",\n            name_str\n        );\n    }\n\n    #[test]\n    fn subject() {\n        let cert = certificate();\n        let subject = cert.subject();\n        let (_, name) = X509Name::from_der(&subject).unwrap();\n        let name_str = name.to_string_with_registry(oid_registry()).unwrap();\n        assert_eq!(\n            \"C=US, ST=California, L=Palo Alto, O=Foobar LLC, OU=Dev Land, CN=foobar.com\",\n            name_str\n        );\n    }\n}\n"
  },
  {
    "path": "security-framework/src/cipher_suite.rs",
    "content": "//! Cipher Suites supported by Secure Transport\n\nuse security_framework_sys::cipher_suite::*;\n\nmacro_rules! make_suites {\n    ($($suite:ident),+) => {\n        /// TLS cipher suites.\n        #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]\n        pub struct CipherSuite(SSLCipherSuite);\n\n        #[allow(missing_docs)]\n        impl CipherSuite {\n            $(\n                pub const $suite: Self = Self($suite);\n            )+\n\n            #[inline(always)]\n            #[must_use]\n            pub const fn from_raw(raw: SSLCipherSuite) -> Self {\n                Self(raw)\n            }\n\n            #[inline(always)]\n            #[must_use]\n            pub const fn to_raw(&self) -> SSLCipherSuite {\n                self.0\n            }\n        }\n    }\n}\n\nmake_suites! {\n    // The commented out ones up here are aliases of the matching TLS suites\n    SSL_NULL_WITH_NULL_NULL,\n    SSL_RSA_WITH_NULL_MD5,\n    SSL_RSA_WITH_NULL_SHA,\n    SSL_RSA_EXPORT_WITH_RC4_40_MD5,\n    SSL_RSA_WITH_RC4_128_MD5,\n    SSL_RSA_WITH_RC4_128_SHA,\n    SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,\n    SSL_RSA_WITH_IDEA_CBC_SHA,\n    SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,\n    SSL_RSA_WITH_DES_CBC_SHA,\n    //SSL_RSA_WITH_3DES_EDE_CBC_SHA,\n    SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,\n    SSL_DH_DSS_WITH_DES_CBC_SHA,\n    //SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,\n    SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,\n    SSL_DH_RSA_WITH_DES_CBC_SHA,\n    //SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,\n    SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,\n    SSL_DHE_DSS_WITH_DES_CBC_SHA,\n    //SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,\n    SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,\n    SSL_DHE_RSA_WITH_DES_CBC_SHA,\n    //SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,\n    SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,\n    //SSL_DH_anon_WITH_RC4_128_MD5,\n    SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,\n    SSL_DH_anon_WITH_DES_CBC_SHA,\n    //SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,\n    SSL_FORTEZZA_DMS_WITH_NULL_SHA,\n    SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,\n\n    /* TLS addenda using AES, per RFC 3268 */\n    TLS_RSA_WITH_AES_128_CBC_SHA,\n    TLS_DH_DSS_WITH_AES_128_CBC_SHA,\n    TLS_DH_RSA_WITH_AES_128_CBC_SHA,\n    TLS_DHE_DSS_WITH_AES_128_CBC_SHA,\n    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,\n    TLS_DH_anon_WITH_AES_128_CBC_SHA,\n    TLS_RSA_WITH_AES_256_CBC_SHA,\n    TLS_DH_DSS_WITH_AES_256_CBC_SHA,\n    TLS_DH_RSA_WITH_AES_256_CBC_SHA,\n    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,\n    TLS_DHE_RSA_WITH_AES_256_CBC_SHA,\n    TLS_DH_anon_WITH_AES_256_CBC_SHA,\n\n    /* ECDSA addenda, RFC 4492 */\n    TLS_ECDH_ECDSA_WITH_NULL_SHA,\n    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,\n    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,\n    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,\n    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,\n    TLS_ECDHE_ECDSA_WITH_NULL_SHA,\n    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,\n    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,\n    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,\n    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,\n    TLS_ECDH_RSA_WITH_NULL_SHA,\n    TLS_ECDH_RSA_WITH_RC4_128_SHA,\n    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,\n    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,\n    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,\n    TLS_ECDHE_RSA_WITH_NULL_SHA,\n    TLS_ECDHE_RSA_WITH_RC4_128_SHA,\n    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,\n    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,\n    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,\n    TLS_ECDH_anon_WITH_NULL_SHA,\n    TLS_ECDH_anon_WITH_RC4_128_SHA,\n    TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,\n    TLS_ECDH_anon_WITH_AES_128_CBC_SHA,\n    TLS_ECDH_anon_WITH_AES_256_CBC_SHA,\n\n    /* TLS 1.2 addenda, RFC 5246 */\n\n    /* Initial state. */\n    TLS_NULL_WITH_NULL_NULL,\n\n    /* Server provided RSA certificate for key exchange. */\n    TLS_RSA_WITH_NULL_MD5,\n    TLS_RSA_WITH_NULL_SHA,\n    TLS_RSA_WITH_RC4_128_MD5,\n    TLS_RSA_WITH_RC4_128_SHA,\n    TLS_RSA_WITH_3DES_EDE_CBC_SHA,\n    //TLS_RSA_WITH_AES_128_CBC_SHA,\n    //TLS_RSA_WITH_AES_256_CBC_SHA,\n    TLS_RSA_WITH_NULL_SHA256,\n    TLS_RSA_WITH_AES_128_CBC_SHA256,\n    TLS_RSA_WITH_AES_256_CBC_SHA256,\n\n    /* Server-authenticated (and optionally client-authenticated) Diffie-Hellman. */\n    TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,\n    TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,\n    TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,\n    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,\n    //TLS_DH_DSS_WITH_AES_128_CBC_SHA,\n    //TLS_DH_RSA_WITH_AES_128_CBC_SHA,\n    //TLS_DHE_DSS_WITH_AES_128_CBC_SHA,\n    //TLS_DHE_RSA_WITH_AES_128_CBC_SHA,\n    //TLS_DH_DSS_WITH_AES_256_CBC_SHA,\n    //TLS_DH_RSA_WITH_AES_256_CBC_SHA,\n    //TLS_DHE_DSS_WITH_AES_256_CBC_SHA,\n    //TLS_DHE_RSA_WITH_AES_256_CBC_SHA,\n    TLS_DH_DSS_WITH_AES_128_CBC_SHA256,\n    TLS_DH_RSA_WITH_AES_128_CBC_SHA256,\n    TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,\n    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,\n    TLS_DH_DSS_WITH_AES_256_CBC_SHA256,\n    TLS_DH_RSA_WITH_AES_256_CBC_SHA256,\n    TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,\n    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,\n\n    /* Completely anonymous Diffie-Hellman */\n    TLS_DH_anon_WITH_RC4_128_MD5,\n    TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,\n    //TLS_DH_anon_WITH_AES_128_CBC_SHA,\n    //TLS_DH_anon_WITH_AES_256_CBC_SHA,\n    TLS_DH_anon_WITH_AES_128_CBC_SHA256,\n    TLS_DH_anon_WITH_AES_256_CBC_SHA256,\n\n    /* Addendum from RFC 4279, TLS PSK */\n\n    TLS_PSK_WITH_RC4_128_SHA,\n    TLS_PSK_WITH_3DES_EDE_CBC_SHA,\n    TLS_PSK_WITH_AES_128_CBC_SHA,\n    TLS_PSK_WITH_AES_256_CBC_SHA,\n    TLS_DHE_PSK_WITH_RC4_128_SHA,\n    TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,\n    TLS_DHE_PSK_WITH_AES_128_CBC_SHA,\n    TLS_DHE_PSK_WITH_AES_256_CBC_SHA,\n    TLS_RSA_PSK_WITH_RC4_128_SHA,\n    TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,\n    TLS_RSA_PSK_WITH_AES_128_CBC_SHA,\n    TLS_RSA_PSK_WITH_AES_256_CBC_SHA,\n\n    /* RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption */\n\n    TLS_PSK_WITH_NULL_SHA,\n    TLS_DHE_PSK_WITH_NULL_SHA,\n    TLS_RSA_PSK_WITH_NULL_SHA,\n\n    /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites\n       for TLS. */\n    TLS_RSA_WITH_AES_128_GCM_SHA256,\n    TLS_RSA_WITH_AES_256_GCM_SHA384,\n    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,\n    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,\n    TLS_DH_RSA_WITH_AES_128_GCM_SHA256,\n    TLS_DH_RSA_WITH_AES_256_GCM_SHA384,\n    TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,\n    TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,\n    TLS_DH_DSS_WITH_AES_128_GCM_SHA256,\n    TLS_DH_DSS_WITH_AES_256_GCM_SHA384,\n    TLS_DH_anon_WITH_AES_128_GCM_SHA256,\n    TLS_DH_anon_WITH_AES_256_GCM_SHA384,\n\n    /* RFC 5487 - PSK with SHA-256/384 and AES GCM */\n    TLS_PSK_WITH_AES_128_GCM_SHA256,\n    TLS_PSK_WITH_AES_256_GCM_SHA384,\n    TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,\n    TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,\n    TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,\n    TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,\n\n    TLS_PSK_WITH_AES_128_CBC_SHA256,\n    TLS_PSK_WITH_AES_256_CBC_SHA384,\n    TLS_PSK_WITH_NULL_SHA256,\n    TLS_PSK_WITH_NULL_SHA384,\n\n    TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,\n    TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,\n    TLS_DHE_PSK_WITH_NULL_SHA256,\n    TLS_DHE_PSK_WITH_NULL_SHA384,\n\n    TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,\n    TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,\n    TLS_RSA_PSK_WITH_NULL_SHA256,\n    TLS_RSA_PSK_WITH_NULL_SHA384,\n\n\n    /* Addenda from rfc 5289  Elliptic Curve Cipher Suites with\n       HMAC SHA-256/384. */\n    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,\n    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,\n    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,\n    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,\n    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,\n    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,\n    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,\n    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,\n\n    /* Addenda from rfc 5289  Elliptic Curve Cipher Suites with\n       SHA-256/384 and AES Galois Counter Mode (GCM) */\n    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\n    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,\n    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,\n    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\n    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,\n    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,\n\n    /* RFC 5746 - Secure Renegotiation */\n    TLS_EMPTY_RENEGOTIATION_INFO_SCSV,\n    /*\n     * Tags for SSL 2 cipher kinds which are not specified\n     * for SSL 3.\n     */\n    SSL_RSA_WITH_RC2_CBC_MD5,\n    SSL_RSA_WITH_IDEA_CBC_MD5,\n    SSL_RSA_WITH_DES_CBC_MD5,\n    SSL_RSA_WITH_3DES_EDE_CBC_MD5,\n    SSL_NO_SUCH_CIPHERSUITE\n}\n"
  },
  {
    "path": "security-framework/src/cms.rs",
    "content": "//! Cryptographic Message Syntax support\n\nuse std::{fmt, ptr};\n\nuse core_foundation::array::CFArray;\nuse core_foundation::base::TCFType;\nuse core_foundation::data::CFData;\nuse core_foundation::string::CFString;\nuse core_foundation_sys::array::CFArrayRef;\nuse core_foundation_sys::base::{OSStatus, TCFTypeRef};\nuse core_foundation_sys::data::CFDataRef;\nuse core_foundation_sys::date::CFAbsoluteTime;\nuse core_foundation_sys::string::CFStringRef;\nuse security_framework_sys::cms::*;\nuse security_framework_sys::trust::SecTrustRef;\n\nuse crate::base::Result;\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::policy::SecPolicy;\nuse crate::trust::SecTrust;\n\npub use decoder::CMSDecoder;\n\npub use encoder::cms_encode_content;\npub use encoder::CMSEncoder;\npub use encoder::SignedAttributes;\npub use encoder::CMS_DIGEST_ALGORITHM_SHA1;\npub use encoder::CMS_DIGEST_ALGORITHM_SHA256;\n\nmod encoder {\n    use super::*;\n    use crate::identity::SecIdentity;\n    use core_foundation::{declare_TCFType, impl_TCFType};\n\n    /// SHA1 digest algorithm\n    pub const CMS_DIGEST_ALGORITHM_SHA1: &str = \"sha1\";\n    /// SHA256 digest algorithm\n    pub const CMS_DIGEST_ALGORITHM_SHA256: &str = \"sha256\";\n\n    bitflags::bitflags! {\n        /// Optional attributes you can add to a signed message\n        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n        pub struct SignedAttributes: CMSSignedAttributes {\n            /// Identify signature, encryption, and digest algorithms supported by the encoder\n            const SMIME_CAPABILITIES = kCMSAttrSmimeCapabilities;\n            /// Indicate that the signing certificate included with the message is the preferred one for S/MIME encryption\n            const SMIME_ENCRYPTION_KEY_PREFS = kCMSAttrSmimeEncryptionKeyPrefs;\n            /// Indicate that the signing certificate included with the message is the preferred one for S/MIME encryption,\n            /// but using an attribute object identifier (OID) preferred by Microsoft\n            const SMIME_MS_ENCRYPTION_KEY_PREFS = kCMSAttrSmimeMSEncryptionKeyPrefs;\n            /// Include the signing time\n            const SIGNING_TIME =  kCMSAttrSigningTime;\n            /// Include Apple codesigning hash agility\n            const APPLE_CODESIGNING_HASH_AGILITY = kCMSAttrAppleCodesigningHashAgility;\n            /// Include Apple codesigning hash agility, version 2\n            const APPLE_CODESIGNING_HASH_AGILITY_V2 = kCMSAttrAppleCodesigningHashAgilityV2;\n            /// Include the expiration time\n            const APPLE_EXPIRATION_TIME = kCMSAttrAppleExpirationTime;\n        }\n    }\n\n    declare_TCFType! {\n        /// A type representing CMS encoder\n        CMSEncoder, CMSEncoderRef\n    }\n    impl_TCFType!(CMSEncoder, CMSEncoderRef, CMSEncoderGetTypeID);\n\n    unsafe impl Sync for CMSEncoder {}\n    unsafe impl Send for CMSEncoder {}\n\n    impl fmt::Debug for CMSEncoder {\n        #[cold]\n        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n            fmt.debug_struct(\"CMSEncoder\").finish()\n        }\n    }\n\n    impl CMSEncoder {\n        /// Create a new instance of `CMSEncoder`\n        pub fn create() -> Result<Self> {\n            let mut inner: CMSEncoderRef = ptr::null_mut();\n            cvt(unsafe { CMSEncoderCreate(&mut inner) })?;\n            Ok(Self(inner))\n        }\n\n        /// Sets the digest algorithm to use for the signer.\n        /// Can be one of the predefined constants:\n        ///\n        /// * `CMS_DIGEST_ALGORITHM_SHA1`\n        /// * `CMS_DIGEST_ALGORITHM_SHA256`\n        pub fn set_signer_algorithm(&self, digest_algorithm: &str) -> Result<()> {\n            let alg = CFString::new(digest_algorithm);\n\n            cvt(unsafe { CMSEncoderSetSignerAlgorithm(self.0, alg.as_concrete_TypeRef()) })?;\n            Ok(())\n        }\n\n        /// Specify signers of the CMS message; implies that the message will be signed\n        pub fn add_signers(&self, signers: &[SecIdentity]) -> Result<()> {\n            let signers = CFArray::from_CFTypes(signers);\n            cvt(unsafe {\n                CMSEncoderAddSigners(\n                    self.0,\n                    if signers.is_empty() { ptr::null() } else { signers.as_CFTypeRef() })\n            })?;\n            Ok(())\n        }\n\n        #[doc(hidden)]\n        pub fn get_signers(&self) -> Result<Vec<SecIdentity>> {\n            self.signers()\n        }\n\n        /// Obtains the array of signers specified with the `add_signers` function\n        pub fn signers(&self) -> Result<Vec<SecIdentity>> {\n            let mut out: CFArrayRef = ptr::null_mut();\n            cvt(unsafe { CMSEncoderCopySigners(self.0, &mut out) })?;\n\n            if out.is_null() {\n                Ok(Vec::new())\n            } else {\n                let array = unsafe { CFArray::<SecIdentity>::wrap_under_create_rule(out) };\n                Ok(array.into_iter().map(|c| c.clone()).collect())\n            }\n        }\n\n        /// Specifies a message is to be encrypted and specifies the recipients of the message\n        pub fn add_recipients(&self, recipients: &[SecCertificate]) -> Result<()> {\n            let recipients = CFArray::from_CFTypes(recipients);\n            cvt(unsafe {\n                CMSEncoderAddRecipients(\n                    self.0,\n                    if recipients.is_empty() { ptr::null() } else { recipients.as_CFTypeRef() },\n                )\n            })?;\n            Ok(())\n        }\n\n        #[doc(hidden)]\n        pub fn get_recipients(&self) -> Result<Vec<SecCertificate>> {\n            self.recipients()\n        }\n\n        /// Obtains the array of recipients specified with the `add_recipients` function\n        pub fn recipients(&self) -> Result<Vec<SecCertificate>> {\n            let mut out: CFArrayRef = ptr::null_mut();\n            cvt(unsafe { CMSEncoderCopyRecipients(self.0, &mut out) })?;\n\n            if out.is_null() {\n                Ok(Vec::new())\n            } else {\n                let array = unsafe { CFArray::<SecCertificate>::wrap_under_create_rule(out) };\n                Ok(array.into_iter().map(|c| c.clone()).collect())\n            }\n        }\n\n        /// Specifies whether the signed data is to be separate from the message\n        pub fn set_has_detached_content(&self, has_detached_content: bool) -> Result<()> {\n            cvt(unsafe { CMSEncoderSetHasDetachedContent(self.0, has_detached_content.into()) })?;\n            Ok(())\n        }\n\n        #[doc(hidden)]\n        pub fn get_has_detached_content(&self) -> Result<bool> {\n            self.has_detached_content()\n        }\n\n        /// Indicates whether the message is to have detached content\n        pub fn has_detached_content(&self) -> Result<bool> {\n            let mut has_detached_content = 0;\n            cvt(unsafe { CMSEncoderGetHasDetachedContent(self.0, &mut has_detached_content) })?;\n            Ok(has_detached_content != 0)\n        }\n\n        /// Specifies an object identifier for the encapsulated data of a signed message\n        pub fn set_encapsulated_content_type_oid(&self, oid: &str) -> Result<()> {\n            let oid = CFString::new(oid);\n            cvt(unsafe { CMSEncoderSetEncapsulatedContentTypeOID(self.0, oid.as_CFTypeRef()) })?;\n            Ok(())\n        }\n\n        #[doc(hidden)]\n        pub fn get_encapsulated_content_type(&self) -> Result<Vec<u8>> {\n            self.encapsulated_content_type()\n        }\n\n        /// Obtains the object identifier for the encapsulated data of a signed message\n        pub fn encapsulated_content_type(&self) -> Result<Vec<u8>> {\n            let mut out: CFDataRef = ptr::null_mut();\n            cvt(unsafe { CMSEncoderCopyEncapsulatedContentType(self.0, &mut out) })?;\n            Ok(unsafe { CFData::wrap_under_create_rule(out).to_vec() })\n        }\n\n        /// Adds certificates to a message\n        pub fn add_supporting_certs(&self, certs: &[SecCertificate]) -> Result<()> {\n            let certs = CFArray::from_CFTypes(certs);\n            cvt(unsafe {\n                CMSEncoderAddSupportingCerts(\n                    self.0,\n                    if !certs.is_empty() { certs.as_CFTypeRef() } else { ptr::null() })\n            })?;\n            Ok(())\n        }\n\n        #[doc(hidden)]\n        pub fn get_supporting_certs(&self) -> Result<Vec<SecCertificate>> {\n            self.supporting_certs()\n        }\n\n        /// Obtains the certificates added to a message with `add_supporting_certs`\n        pub fn supporting_certs(&self) -> Result<Vec<SecCertificate>> {\n            let mut out: CFArrayRef = ptr::null_mut();\n            cvt(unsafe { CMSEncoderCopySupportingCerts(self.0, &mut out) })?;\n\n            if out.is_null() {\n                Ok(Vec::new())\n            } else {\n                let array = unsafe { CFArray::<SecCertificate>::wrap_under_create_rule(out) };\n                Ok(array.into_iter().map(|c| c.clone()).collect())\n            }\n        }\n\n        /// Specifies attributes for a signed message\n        pub fn add_signed_attributes(&self, signed_attributes: SignedAttributes) -> Result<()> {\n            cvt(unsafe { CMSEncoderAddSignedAttributes(self.0, signed_attributes.bits()) })?;\n            Ok(())\n        }\n\n        /// Specifies which certificates to include in a signed CMS message\n        pub fn set_certificate_chain_mode(&self, certificate_chain_mode: CMSCertificateChainMode) -> Result<()> {\n            cvt(unsafe { CMSEncoderSetCertificateChainMode(self.0, certificate_chain_mode) })?;\n            Ok(())\n        }\n\n        #[doc(hidden)]\n        pub fn get_certificate_chain_mode(&self) -> Result<CMSCertificateChainMode> {\n            self.certificate_chain_mode()\n        }\n\n        /// Obtains a constant that indicates which certificates are to be included in a signed CMS message\n        pub fn certificate_chain_mode(&self) -> Result<CMSCertificateChainMode> {\n            let mut out = CMSCertificateChainMode::kCMSCertificateNone;\n            cvt(unsafe { CMSEncoderGetCertificateChainMode(self.0, &mut out) })?;\n            Ok(out)\n        }\n\n        /// Feeds content bytes into the encoder\n        pub fn update_content(&self, content: &[u8]) -> Result<()> {\n            cvt(unsafe { CMSEncoderUpdateContent(self.0, content.as_ptr().cast(), content.len()) })?;\n            Ok(())\n        }\n\n        #[doc(hidden)]\n        pub fn get_encoded_content(&self) -> Result<Vec<u8>> {\n            self.encoded_content()\n        }\n\n        /// Finishes encoding the message and obtains the encoded result\n        pub fn encoded_content(&self) -> Result<Vec<u8>> {\n            let mut out: CFDataRef = ptr::null_mut();\n            cvt(unsafe { CMSEncoderCopyEncodedContent(self.0, &mut out) })?;\n            Ok(unsafe { CFData::wrap_under_create_rule(out).to_vec() })\n        }\n\n        #[doc(hidden)]\n        pub fn get_signer_timestamp(&self, signer_index: usize) -> Result<CFAbsoluteTime> {\n            self.signer_timestamp(signer_index)\n        }\n\n        /// Returns the timestamp of a signer of a CMS message, if present\n        pub fn signer_timestamp(&self, signer_index: usize) -> Result<CFAbsoluteTime> {\n            let mut out = CFAbsoluteTime::default();\n            cvt(unsafe { CMSEncoderCopySignerTimestamp(self.0, signer_index, &mut out) })?;\n            Ok(out)\n        }\n\n        #[doc(hidden)]\n        pub fn get_signer_timestamp_with_policy(&self, timestamp_policy: Option<CFStringRef>, signer_index: usize) -> Result<CFAbsoluteTime> {\n            self.signer_timestamp_with_policy(timestamp_policy, signer_index)\n        }\n\n        /// Returns the timestamp of a signer of a CMS message using a particular policy, if present\n        pub fn signer_timestamp_with_policy(&self, timestamp_policy: Option<CFStringRef>, signer_index: usize) -> Result<CFAbsoluteTime> {\n            let mut out = CFAbsoluteTime::default();\n            cvt(unsafe {\n                CMSEncoderCopySignerTimestampWithPolicy(\n                    self.0,\n                    timestamp_policy.map(|p| p.as_void_ptr()).unwrap_or(ptr::null()),\n                    signer_index,\n                    &mut out,\n                )\n            })?;\n\n            Ok(out)\n        }\n    }\n\n    /// Encodes a message and obtains the result in one high-level function call\n    pub fn cms_encode_content(\n        signers: &[SecIdentity],\n        recipients: &[SecCertificate],\n        content_type_oid: Option<&str>,\n        detached_content: bool,\n        signed_attributes: SignedAttributes,\n        content: &[u8],\n    ) -> Result<Vec<u8>> {\n        let mut out: CFDataRef = ptr::null_mut();\n        let signers = CFArray::from_CFTypes(signers);\n        let recipients = CFArray::from_CFTypes(recipients);\n        let content_type_oid = content_type_oid.map(CFString::new);\n\n        cvt(unsafe {\n            CMSEncodeContent(\n                if signers.is_empty() { ptr::null() } else { signers.as_CFTypeRef() },\n                if recipients.is_empty() { ptr::null() } else { recipients.as_CFTypeRef() },\n                content_type_oid.as_ref().map(|oid| oid.as_CFTypeRef()).unwrap_or(ptr::null()),\n                detached_content.into(),\n                signed_attributes.bits(),\n                content.as_ptr().cast(),\n                content.len(),\n                &mut out,\n            )\n        })?;\n\n        Ok(unsafe { CFData::wrap_under_create_rule(out).to_vec() })\n    }\n}\n\nmod decoder {\n    use super::*;\n    use core_foundation::{declare_TCFType, impl_TCFType};\n\n    /// Holds a result of the `CMSDecoder::get_signer_status` function\n    pub struct SignerStatus {\n        /// Signature status\n        pub signer_status: CMSSignerStatus,\n        /// Trust instance that was used to verify the signer’s certificate\n        pub sec_trust: SecTrust,\n        /// Result of the certificate verification\n        pub cert_verify_result: Result<()>,\n    }\n\n    declare_TCFType! {\n        /// A type representing CMS Decoder\n        CMSDecoder, CMSDecoderRef\n    }\n    impl_TCFType!(CMSDecoder, CMSDecoderRef, CMSDecoderGetTypeID);\n\n    unsafe impl Sync for CMSDecoder {}\n    unsafe impl Send for CMSDecoder {}\n\n    impl fmt::Debug for CMSDecoder {\n        #[cold]\n        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n            fmt.debug_struct(\"CMSDecoder\").finish()\n        }\n    }\n\n    impl CMSDecoder {\n        /// Create a new instance of `CMSDecoder`\n        pub fn create() -> Result<Self> {\n            let mut inner: CMSDecoderRef = ptr::null_mut();\n            cvt(unsafe { CMSDecoderCreate(&mut inner) })?;\n            Ok(Self(inner))\n        }\n\n        /// Feeds raw bytes of the message to be decoded into the decoder\n        pub fn update_message(&self, message: &[u8]) -> Result<()> {\n            cvt(unsafe { CMSDecoderUpdateMessage(self.0, message.as_ptr().cast(), message.len()) })?;\n            Ok(())\n        }\n\n        /// Indicates that there is no more data to decode\n        pub fn finalize_message(&self) -> Result<()> {\n            cvt(unsafe { CMSDecoderFinalizeMessage(self.0) })?;\n            Ok(())\n        }\n\n        /// Specifies the message’s detached content, if any\n        pub fn set_detached_content(&self, detached_content: &[u8]) -> Result<()> {\n            let data = CFData::from_buffer(detached_content);\n            cvt(unsafe { CMSDecoderSetDetachedContent(self.0, data.as_concrete_TypeRef()) })?;\n            Ok(())\n        }\n\n        /// Obtains the detached content specified with the `set_detached_content` function\n        pub fn get_detached_content(&self) -> Result<Vec<u8>> {\n            unsafe {\n                let mut out: CFDataRef = ptr::null_mut();\n                cvt(CMSDecoderCopyDetachedContent(self.0, &mut out))?;\n                if out.is_null() {\n                    Ok(Vec::new())\n                } else {\n                    Ok(CFData::wrap_under_create_rule(out).to_vec())\n                }\n            }\n        }\n\n        /// Obtains the number of signers of a message\n        pub fn get_num_signers(&self) -> Result<usize> {\n            let mut out = 0;\n            cvt(unsafe { CMSDecoderGetNumSigners(self.0, &mut out) })?;\n            Ok(out)\n        }\n\n        /// Obtains the status of a CMS message’s signature\n        pub fn get_signer_status(\n            &self,\n            signer_index: usize,\n            policies: &[SecPolicy],\n        ) -> Result<SignerStatus> {\n            let policies = CFArray::from_CFTypes(policies);\n\n            let mut signer_status = CMSSignerStatus::kCMSSignerUnsigned;\n            let mut sec_trust: SecTrustRef = ptr::null_mut();\n            let mut verify_result = OSStatus::default();\n\n            cvt(unsafe {\n                CMSDecoderCopySignerStatus(\n                    self.0,\n                    signer_index,\n                    if policies.is_empty() { ptr::null() } else { policies.as_CFTypeRef() },\n                    true.into(),\n                    &mut signer_status,\n                    &mut sec_trust,\n                    &mut verify_result,\n                )\n            })?;\n\n            Ok(SignerStatus {\n                signer_status,\n                sec_trust: unsafe { SecTrust::wrap_under_create_rule(sec_trust) },\n                cert_verify_result: cvt(verify_result),\n            })\n        }\n\n        /// Obtains the email address of the specified signer of a CMS message\n        pub fn get_signer_email_address(&self, signer_index: usize) -> Result<String> {\n            let mut out: CFStringRef = ptr::null_mut();\n            cvt(unsafe { CMSDecoderCopySignerEmailAddress(self.0, signer_index, &mut out) })?;\n            Ok(unsafe { CFString::wrap_under_create_rule(out).to_string() })\n        }\n\n        /// Determines whether a CMS message was encrypted\n        pub fn is_content_encrypted(&self) -> Result<bool> {\n            let mut out = 0;\n            cvt(unsafe { CMSDecoderIsContentEncrypted(self.0, &mut out) })?;\n            Ok(out != 0)\n        }\n\n        /// Obtains the object identifier for the encapsulated data of a signed message\n        pub fn get_encapsulated_content_type(&self) -> Result<Vec<u8>> {\n            let mut out: CFDataRef = ptr::null_mut();\n            if out.is_null() {\n                Ok(Vec::new())\n            } else {\n                cvt(unsafe { CMSDecoderCopyEncapsulatedContentType(self.0, &mut out) })?;\n                Ok(unsafe { CFData::wrap_under_create_rule(out).to_vec() })\n            }\n        }\n\n        /// Obtains an array of all of the certificates in a message\n        pub fn get_all_certs(&self) -> Result<Vec<SecCertificate>> {\n            let mut out: CFArrayRef = ptr::null_mut();\n            cvt(unsafe { CMSDecoderCopyAllCerts(self.0, &mut out) })?;\n\n            if out.is_null() {\n                Ok(Vec::new())\n            } else {\n                let array = unsafe { CFArray::<SecCertificate>::wrap_under_create_rule(out) };\n                Ok(array.into_iter().map(|c| c.clone()).collect())\n            }\n        }\n\n        /// Obtains the message content, if any\n        pub fn get_content(&self) -> Result<Vec<u8>> {\n            let mut out: CFDataRef = ptr::null_mut();\n\n            cvt(unsafe { CMSDecoderCopyContent(self.0, &mut out) })?;\n\n            if out.is_null() {\n                Ok(Vec::new())\n            } else {\n                Ok(unsafe { CFData::wrap_under_create_rule(out).to_vec() })\n            }\n        }\n\n        /// Obtains the signing time of a CMS message, if present\n        pub fn get_signer_signing_time(&self, signer_index: usize) -> Result<CFAbsoluteTime> {\n            let mut out = CFAbsoluteTime::default();\n            cvt(unsafe { CMSDecoderCopySignerSigningTime(self.0, signer_index, &mut out) })?;\n            Ok(out)\n        }\n\n        /// Returns the timestamp of a signer of a CMS message, if present\n        pub fn get_signer_timestamp(&self, signer_index: usize) -> Result<CFAbsoluteTime> {\n            let mut out = CFAbsoluteTime::default();\n            cvt(unsafe { CMSDecoderCopySignerTimestamp(self.0, signer_index, &mut out) })?;\n            Ok(out)\n        }\n\n        /// Returns the timestamp of a signer of a CMS message using a given policy, if present\n        pub fn get_signer_timestamp_with_policy(\n            &self,\n            timestamp_policy: Option<CFStringRef>,\n            signer_index: usize,\n        ) -> Result<CFAbsoluteTime> {\n            let mut out = CFAbsoluteTime::default();\n            cvt(unsafe {\n                CMSDecoderCopySignerTimestampWithPolicy(\n                    self.0,\n                    timestamp_policy.map(|p| p.as_void_ptr()).unwrap_or(ptr::null()),\n                    signer_index,\n                    &mut out,\n                )\n            })?;\n\n            Ok(out)\n        }\n\n        /// Returns an array containing the certificates from a timestamp response\n        pub fn get_signer_timestamp_certificates(&self, signer_index: usize) -> Result<Vec<SecCertificate>> {\n            let mut out: CFArrayRef = ptr::null_mut();\n            cvt(unsafe { CMSDecoderCopySignerTimestampCertificates(self.0, signer_index, &mut out) })?;\n\n            if out.is_null() {\n                Ok(Vec::new())\n            } else {\n                let array = unsafe { CFArray::<SecCertificate>::wrap_under_create_rule(out) };\n                Ok(array.into_iter().map(|c| c.clone()).collect())\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::cms::{cms_encode_content, CMSDecoder, SignedAttributes};\n    use crate::import_export::{ImportedIdentity, Pkcs12ImportOptions};\n    use crate::policy::SecPolicy;\n    use security_framework_sys::cms::CMSSignerStatus;\n    use std::sync::OnceLock;\n\n    const KEYSTORE: &[u8] = include_bytes!(\"../test/cms/keystore.p12\");\n    const ENCRYPTED_CMS: &[u8] = include_bytes!(\"../test/cms/encrypted.p7m\");\n    const SIGNED_ENCRYPTED_CMS: &[u8] = include_bytes!(\"../test/cms/signed-encrypted.p7m\");\n    static KEYSTORE_IDENTITY: OnceLock<Vec<ImportedIdentity>> = OnceLock::new();\n\n    fn import_keystore() -> &'static [ImportedIdentity] {\n        KEYSTORE_IDENTITY.get_or_init(|| {\n            let mut import_opts = Pkcs12ImportOptions::new();\n            import_opts.passphrase(\"cms\").import(KEYSTORE).expect(\"import keystore.p12\")\n        })\n    }\n\n    #[test]\n    fn test_decode_encrypted_with_keystore_identities() {\n        let _ = import_keystore();\n\n        let decoder = CMSDecoder::create().expect(\"create\");\n        decoder.update_message(ENCRYPTED_CMS).expect(\"update\");\n        decoder.finalize_message().expect(\"finalize\");\n\n        assert!(decoder.is_content_encrypted().unwrap());\n        assert_eq!(decoder.get_content().unwrap(), b\"encrypted message\\n\");\n        assert_eq!(decoder.get_all_certs().unwrap().len(), 0);\n        assert_eq!(decoder.get_num_signers().unwrap(), 0);\n    }\n\n    #[test]\n    fn test_decode_signed_and_encrypted_with_keystore_identities() {\n        let _ = import_keystore();\n\n        let decoder = CMSDecoder::create().unwrap();\n        decoder.update_message(SIGNED_ENCRYPTED_CMS).unwrap();\n        decoder.finalize_message().unwrap();\n\n        assert!(decoder.is_content_encrypted().unwrap());\n\n        let signed_content = decoder.get_content().unwrap();\n\n        let decoder2 = CMSDecoder::create().unwrap();\n        decoder2.update_message(&signed_content).unwrap();\n        decoder2.finalize_message().unwrap();\n        assert_eq!(decoder2.get_content().unwrap(), b\"encrypted message\\n\");\n        assert_eq!(decoder2.get_num_signers().unwrap(), 1);\n\n        let policies = vec![SecPolicy::create_x509()];\n        let status = decoder2.get_signer_status(0, &policies).unwrap();\n        assert!(status.cert_verify_result.is_err());\n        assert_eq!(status.signer_status, CMSSignerStatus::kCMSSignerInvalidCert);\n    }\n\n    #[test]\n    fn test_encode_encrypted_with_keystore_identities() {\n        let identities = import_keystore();\n\n        let chain = identities\n            .iter().find_map(|id| id.cert_chain.as_ref())\n            .unwrap();\n\n        let message = cms_encode_content(\n            &[],\n            &chain[0..1],\n            None,\n            false,\n            SignedAttributes::empty(),\n            b\"encrypted message\\n\",\n        ).unwrap();\n\n        let decoder = CMSDecoder::create().unwrap();\n        decoder.update_message(&message).unwrap();\n        decoder.finalize_message().unwrap();\n        assert_eq!(decoder.get_content().unwrap(), b\"encrypted message\\n\");\n    }\n\n    #[test]\n    fn test_encode_signed_encrypted_with_keystore_identities() {\n        let identities = import_keystore();\n\n        let chain = identities\n            .iter().find_map(|id| id.cert_chain.as_ref())\n            .unwrap();\n\n        let identity = identities\n            .iter().find_map(|id| id.identity.as_ref())\n            .unwrap();\n\n        let message = cms_encode_content(\n            std::slice::from_ref(identity),\n            &chain[0..1],\n            None,\n            false,\n            SignedAttributes::empty(),\n            b\"encrypted message\\n\",\n        ).unwrap();\n\n        let decoder = CMSDecoder::create().unwrap();\n        decoder.update_message(&message).unwrap();\n        decoder.finalize_message().unwrap();\n        assert_eq!(decoder.get_content().unwrap(), b\"encrypted message\\n\");\n        assert_eq!(decoder.get_num_signers().unwrap(), 1);\n    }\n\n    #[test]\n    fn test_encode_with_cms_encoder_with_keystore_identities() {\n        let identities = import_keystore();\n\n        let chain = identities\n            .iter().find_map(|id| id.cert_chain.as_ref())\n            .unwrap();\n\n        let identity = identities\n            .iter().find_map(|id| id.identity.as_ref())\n            .unwrap();\n\n        let message = cms_encode_content(\n            std::slice::from_ref(identity),\n            &chain[0..1],\n            None,\n            false,\n            SignedAttributes::empty(),\n            b\"encrypted message\\n\",\n        ).unwrap();\n\n        let decoder = CMSDecoder::create().unwrap();\n        decoder.update_message(&message).unwrap();\n        decoder.finalize_message().unwrap();\n        assert_eq!(decoder.get_content().unwrap(), b\"encrypted message\\n\");\n        assert_eq!(decoder.get_num_signers().unwrap(), 1);\n    }\n}\n"
  },
  {
    "path": "security-framework/src/identity.rs",
    "content": "//! Identity support.\n\nuse core_foundation::base::{TCFType, ToVoid};\nuse core_foundation::dictionary::CFMutableDictionary;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse security_framework_sys::base::SecIdentityRef;\nuse security_framework_sys::identity::{\n    SecIdentityCopyCertificate, SecIdentityCopyPrivateKey, SecIdentityGetTypeID,\n};\nuse security_framework_sys::item::kSecValueRef;\nuse security_framework_sys::keychain_item::SecItemDelete;\nuse std::fmt;\nuse std::ptr;\n\nuse crate::base::{Error, Result};\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::key::SecKey;\n\ndeclare_TCFType! {\n    /// A type representing an identity.\n    ///\n    /// Identities are a certificate paired with the corresponding private key.\n    SecIdentity, SecIdentityRef\n}\nimpl_TCFType!(SecIdentity, SecIdentityRef, SecIdentityGetTypeID);\n\nunsafe impl Sync for SecIdentity {}\nunsafe impl Send for SecIdentity {}\n\nimpl fmt::Debug for SecIdentity {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let mut builder = fmt.debug_struct(\"SecIdentity\");\n        if let Ok(cert) = self.certificate() {\n            builder.field(\"certificate\", &cert);\n        }\n        if let Ok(key) = self.private_key() {\n            builder.field(\"private_key\", &key);\n        }\n        builder.finish()\n    }\n}\n\nimpl SecIdentity {\n    /// Returns the certificate corresponding to this identity.\n    pub fn certificate(&self) -> Result<SecCertificate> {\n        unsafe {\n            let mut certificate = ptr::null_mut();\n            cvt(SecIdentityCopyCertificate(self.0, &mut certificate))?;\n            Ok(SecCertificate::wrap_under_create_rule(certificate))\n        }\n    }\n\n    /// Returns the private key corresponding to this identity.\n    pub fn private_key(&self) -> Result<SecKey> {\n        unsafe {\n            let mut key = ptr::null_mut();\n            cvt(SecIdentityCopyPrivateKey(self.0, &mut key))?;\n            Ok(SecKey::wrap_under_create_rule(key))\n        }\n    }\n\n    /// Translates to `SecItemDelete`, passing in the `SecIdentityRef`\n    pub fn delete(&self) -> Result<(), Error> {\n        let query = CFMutableDictionary::from_CFType_pairs(&[(\n            unsafe { kSecValueRef }.to_void(),\n            self.to_void(),\n        )]);\n\n        cvt(unsafe { SecItemDelete(query.as_concrete_TypeRef()) })\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::SecIdentity;\n\n    #[test]\n    fn identity_has_send_bound() {\n        fn assert_send<T: Send>() {}\n        assert_send::<SecIdentity>();\n    }\n}\n"
  },
  {
    "path": "security-framework/src/import_export.rs",
    "content": "//! Security Framework type import/export support.\n\nuse core_foundation::array::CFArray;\nuse core_foundation::base::{CFType, TCFType};\nuse core_foundation::data::CFData;\nuse core_foundation::dictionary::CFDictionary;\nuse core_foundation::string::CFString;\nuse security_framework_sys::import_export::*;\nuse std::ptr;\n\nuse crate::base::Result;\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::identity::SecIdentity;\n#[cfg(target_os = \"macos\")]\nuse crate::os::macos::access::SecAccess;\n#[cfg(target_os = \"macos\")]\nuse crate::os::macos::keychain::SecKeychain;\nuse crate::trust::SecTrust;\n\n/// Information about an imported identity.\n#[derive(Clone)]\n#[non_exhaustive]\npub struct ImportedIdentity {\n    /// The label of the identity.\n    pub label: Option<String>,\n    /// The ID of the identity. Typically the SHA-1 hash of the public key.\n    pub key_id: Option<Vec<u8>>,\n    /// A `SecTrust` object set up to validate this identity.\n    pub trust: Option<SecTrust>,\n    /// A certificate chain validating this identity.\n    pub cert_chain: Option<Vec<SecCertificate>>,\n    /// The identity itself.\n    pub identity: Option<SecIdentity>,\n}\n\n/// A builder type to import an identity from PKCS#12 formatted data.\n#[derive(Default)]\npub struct Pkcs12ImportOptions {\n    passphrase: Option<CFString>,\n    #[cfg(target_os = \"macos\")]\n    keychain: Option<SecKeychain>,\n    #[cfg(target_os = \"macos\")]\n    access: Option<SecAccess>,\n}\n\n#[cfg(target_os = \"macos\")]\nimpl Pkcs12ImportOptions {\n    /// Specifies macOS keychain in which to import the identity.\n    ///\n    /// If this is not called, the default keychain will be used.\n    #[inline(always)]\n    pub fn keychain(&mut self, keychain: SecKeychain) -> &mut Self {\n        self.keychain = Some(keychain);\n        self\n    }\n\n    /// Specifies the access control to be associated with the identity. macOS only.\n    #[inline(always)]\n    pub fn access(&mut self, access: SecAccess) -> &mut Self {\n        self.access = Some(access);\n        self\n    }\n}\n\nimpl Pkcs12ImportOptions {\n    /// Creates a new builder with default options.\n    #[inline(always)]\n    #[must_use]\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    /// Specifies the passphrase to be used to decrypt the data.\n    ///\n    /// This must be specified, as unencrypted PKCS#12 data is not supported.\n    #[inline]\n    pub fn passphrase(&mut self, passphrase: &str) -> &mut Self {\n        self.passphrase = Some(CFString::new(passphrase));\n        self\n    }\n\n    /// Imports identities from PKCS#12 encoded data.\n    pub fn import(&self, pkcs12_data: &[u8]) -> Result<Vec<ImportedIdentity>> {\n        unsafe {\n            let pkcs12_data = CFData::from_buffer(pkcs12_data);\n\n            let mut options = vec![];\n\n            if let Some(passphrase) = &self.passphrase {\n                options.push((\n                    CFString::wrap_under_get_rule(kSecImportExportPassphrase),\n                    passphrase.as_CFType(),\n                ));\n            }\n\n            self.import_setup(&mut options);\n\n            let options = CFDictionary::from_CFType_pairs(&options);\n\n            let mut raw_items = ptr::null();\n            cvt(SecPKCS12Import(\n                pkcs12_data.as_concrete_TypeRef(),\n                options.as_concrete_TypeRef(),\n                &mut raw_items,\n            ))?;\n            let raw_items = CFArray::<CFDictionary<CFString, *const _>>::wrap_under_create_rule(raw_items);\n\n            let mut items = vec![];\n\n            for raw_item in &raw_items {\n                let label = raw_item\n                    .find(kSecImportItemLabel)\n                    .map(|label| CFString::wrap_under_get_rule((*label).cast()).to_string());\n                let key_id = raw_item\n                    .find(kSecImportItemKeyID)\n                    .map(|key_id| CFData::wrap_under_get_rule((*key_id).cast()).to_vec());\n                let trust = raw_item\n                    .find(kSecImportItemTrust)\n                    .map(|trust| SecTrust::wrap_under_get_rule(*trust as *mut _));\n                let cert_chain = raw_item\n                    .find(kSecImportItemCertChain)\n                    .map(|cert_chain| {\n                        CFArray::<SecCertificate>::wrap_under_get_rule((*cert_chain).cast())\n                            .iter()\n                            .map(|c| c.clone())\n                            .collect()\n                    });\n                let identity = raw_item\n                    .find(kSecImportItemIdentity)\n                    .map(|identity| SecIdentity::wrap_under_get_rule(*identity as *mut _));\n\n                items.push(ImportedIdentity {\n                    label,\n                    key_id,\n                    trust,\n                    cert_chain,\n                    identity,\n                });\n            }\n\n            Ok(items)\n        }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    fn import_setup(&self, options: &mut Vec<(CFString, CFType)>) {\n        unsafe {\n            if let Some(keychain) = &self.keychain {\n                options.push((\n                    CFString::wrap_under_get_rule(kSecImportExportKeychain),\n                    keychain.as_CFType(),\n                ));\n            }\n\n            if let Some(access) = &self.access {\n                options.push((\n                    CFString::wrap_under_get_rule(kSecImportExportAccess),\n                    access.as_CFType(),\n                ));\n            }\n        }\n    }\n\n    #[cfg(not(target_os = \"macos\"))]\n    fn import_setup(&self, _: &mut Vec<(CFString, CFType)>) {}\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n\n    #[test]\n    fn missing_passphrase() {\n        let data = include_bytes!(\"../test/server.p12\");\n        assert!(Pkcs12ImportOptions::new().import(data).is_err());\n    }\n}\n"
  },
  {
    "path": "security-framework/src/item.rs",
    "content": "//! Support to search for items in a keychain.\n\nuse core_foundation::array::CFArray;\nuse core_foundation::base::{CFType, TCFType, ToVoid};\nuse core_foundation::boolean::CFBoolean;\nuse core_foundation::data::CFData;\nuse core_foundation::date::CFDate;\nuse core_foundation::dictionary::{CFDictionary, CFMutableDictionary};\nuse core_foundation::number::CFNumber;\nuse core_foundation::string::CFString;\nuse core_foundation_sys::base::{CFCopyDescription, CFGetTypeID, CFRelease, CFTypeRef};\nuse core_foundation_sys::string::CFStringRef;\nuse security_framework_sys::item::*;\nuse security_framework_sys::keychain_item::{\n    SecItemAdd, SecItemCopyMatching, SecItemDelete, SecItemUpdate,\n};\nuse std::collections::HashMap;\nuse std::fmt;\nuse std::ptr;\n\nuse crate::base::Result;\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::identity::SecIdentity;\nuse crate::key::SecKey;\n#[cfg(target_os = \"macos\")]\nuse crate::os::macos::keychain::SecKeychain;\n\n/// Specifies the type of items to search for.\n#[derive(Debug, Copy, Clone)]\npub struct ItemClass(CFStringRef);\n\nimpl ItemClass {\n    /// Look for `SecKeychainItem`s corresponding to generic passwords.\n    #[inline(always)]\n    #[must_use]\n    pub fn generic_password() -> Self {\n        unsafe { Self(kSecClassGenericPassword) }\n    }\n\n    /// Look for `SecKeychainItem`s corresponding to internet passwords.\n    #[inline(always)]\n    #[must_use]\n    pub fn internet_password() -> Self {\n        unsafe { Self(kSecClassInternetPassword) }\n    }\n\n    /// Look for `SecCertificate`s.\n    #[inline(always)]\n    #[must_use]\n    pub fn certificate() -> Self {\n        unsafe { Self(kSecClassCertificate) }\n    }\n\n    /// Look for `SecKey`s.\n    #[inline(always)]\n    #[must_use]\n    pub fn key() -> Self {\n        unsafe { Self(kSecClassKey) }\n    }\n\n    /// Look for `SecIdentity`s.\n    #[inline(always)]\n    #[must_use]\n    pub fn identity() -> Self {\n        unsafe { Self(kSecClassIdentity) }\n    }\n}\n\n/// Specifies the type of keys to search for.\n#[derive(Debug, Copy, Clone)]\npub struct KeyClass(CFStringRef);\n\nimpl KeyClass {\n    /// `kSecAttrKeyClassPublic`\n    #[inline(always)]\n    #[must_use]\n    pub fn public() -> Self {\n        unsafe { Self(kSecAttrKeyClassPublic) }\n    }\n\n    /// `kSecAttrKeyClassPrivate`\n    #[inline(always)]\n    #[must_use]\n    pub fn private() -> Self {\n        unsafe { Self(kSecAttrKeyClassPrivate) }\n    }\n\n    /// `kSecAttrKeyClassSymmetric`\n    #[inline(always)]\n    #[must_use]\n    pub fn symmetric() -> Self {\n        unsafe { Self(kSecAttrKeyClassSymmetric) }\n    }\n}\n\n/// Specifies the number of results returned by a search\n#[derive(Debug, Copy, Clone)]\npub enum Limit {\n    /// Always return all results\n    All,\n\n    /// Return up to the specified number of results\n    Max(i64),\n}\n\nimpl Limit {\n    #[inline]\n    fn to_value(self) -> CFType {\n        match self {\n            Self::All => unsafe { CFString::wrap_under_get_rule(kSecMatchLimitAll).into_CFType() },\n            Self::Max(l) => CFNumber::from(l).into_CFType(),\n        }\n    }\n}\n\nimpl From<i64> for Limit {\n    #[inline]\n    fn from(limit: i64) -> Self {\n        Self::Max(limit)\n    }\n}\n\n/// Specifies whether a search should match cloud-synchronized items.\n#[derive(Debug, Copy, Clone)]\npub enum CloudSync {\n    /// Match only items that are cloud-synchronized.\n    MatchSyncYes,\n    /// Match only items that are not cloud-synchronized.\n    MatchSyncNo,\n    /// Match items whether they are cloud-synchronized or not.\n    MatchSyncAny,\n}\n\nimpl From<Option<bool>> for CloudSync {\n    #[inline]\n    fn from(is_sync: Option<bool>) -> Self {\n        match is_sync {\n            Some(true) => Self::MatchSyncYes,\n            Some(false) => Self::MatchSyncNo,\n            None => Self::MatchSyncAny,\n        }\n    }\n}\n\n/// A builder type to search for items in keychains.\n#[derive(Default)]\npub struct ItemSearchOptions {\n    #[cfg(target_os = \"macos\")]\n    keychains: Option<CFArray<SecKeychain>>,\n    #[cfg(not(target_os = \"macos\"))]\n    keychains: Option<CFArray<CFType>>,\n    ignore_legacy_keychains: bool, // defined everywhere, only consulted on macOS\n    case_insensitive: Option<bool>,\n    class: Option<ItemClass>,\n    key_class: Option<KeyClass>,\n    load_refs: bool,\n    load_attributes: bool,\n    load_data: bool,\n    limit: Option<Limit>,\n    trusted_only: Option<bool>,\n    label: Option<CFString>,\n    service: Option<CFString>,\n    subject: Option<CFString>,\n    account: Option<CFString>,\n    access_group: Option<CFString>,\n    cloud_sync: Option<CloudSync>,\n    pub_key_hash: Option<CFData>,\n    serial_number: Option<CFData>,\n    app_label: Option<CFData>,\n    authentication_context: Option<CFType>,\n    skip_authenticated_items: bool,\n}\n\n#[cfg(target_os = \"macos\")]\nimpl ItemSearchOptions {\n    /// Search within the specified macOS keychains.\n    ///\n    /// If this is not called, the default keychain will be searched.\n    #[inline]\n    pub fn keychains(&mut self, keychains: &[SecKeychain]) -> &mut Self {\n        self.keychains = Some(CFArray::from_CFTypes(keychains));\n        self\n    }\n\n    /// Only search the protected data macOS keychains.\n    ///\n    /// Has no effect if a legacy keychain has been explicitly specified\n    /// using [keychains](ItemSearchOptions::keychains).\n    ///\n    /// Has no effect except in sandboxed applications on macOS 10.15 and above\n    #[inline]\n    pub fn ignore_legacy_keychains(&mut self) -> &mut Self {\n        self.ignore_legacy_keychains = true;\n        self\n    }\n}\n\nimpl ItemSearchOptions {\n    /// Creates a new builder with default options.\n    #[inline(always)]\n    #[must_use]\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    /// Search only for items of the specified class.\n    #[inline(always)]\n    pub fn class(&mut self, class: ItemClass) -> &mut Self {\n        self.class = Some(class);\n        self\n    }\n\n    /// Whether search for an item should be case insensitive or not.\n    #[inline(always)]\n    pub fn case_insensitive(&mut self, case_insensitive: Option<bool>) -> &mut Self {\n        self.case_insensitive = case_insensitive;\n        self\n    }\n\n    /// Search only for keys of the specified class. Also sets self.class to\n    /// `ItemClass::key()`.\n    #[inline(always)]\n    pub fn key_class(&mut self, key_class: KeyClass) -> &mut Self {\n        self.class(ItemClass::key());\n        self.key_class = Some(key_class);\n        self\n    }\n\n    /// Load Security Framework objects (`SecCertificate`, `SecKey`, etc) for\n    /// the results.\n    #[inline(always)]\n    pub fn load_refs(&mut self, load_refs: bool) -> &mut Self {\n        self.load_refs = load_refs;\n        self\n    }\n\n    /// Load Security Framework object attributes for\n    /// the results.\n    #[inline(always)]\n    pub fn load_attributes(&mut self, load_attributes: bool) -> &mut Self {\n        self.load_attributes = load_attributes;\n        self\n    }\n\n    /// Load Security Framework objects data for\n    /// the results.\n    #[inline(always)]\n    pub fn load_data(&mut self, load_data: bool) -> &mut Self {\n        self.load_data = load_data;\n        self\n    }\n\n    /// Limit the number of search results.\n    ///\n    /// If this is not called, the default limit is 1.\n    #[inline(always)]\n    pub fn limit<T: Into<Limit>>(&mut self, limit: T) -> &mut Self {\n        self.limit = Some(limit.into());\n        self\n    }\n\n    /// Search for an item with the given label.\n    #[inline(always)]\n    pub fn label(&mut self, label: &str) -> &mut Self {\n        self.label = Some(CFString::new(label));\n        self\n    }\n\n    /// Whether untrusted certificates should be returned.\n    #[inline(always)]\n    pub fn trusted_only(&mut self, trusted_only: Option<bool>) -> &mut Self {\n        self.trusted_only = trusted_only;\n        self\n    }\n\n    /// Search for an item with the given service.\n    #[inline(always)]\n    pub fn service(&mut self, service: &str) -> &mut Self {\n        self.service = Some(CFString::new(service));\n        self\n    }\n\n    /// Search for an item with exactly the given subject.\n    #[inline(always)]\n    pub fn subject(&mut self, subject: &str) -> &mut Self {\n        self.subject = Some(CFString::new(subject));\n        self\n    }\n\n    /// Search for an item with the given account.\n    #[inline(always)]\n    pub fn account(&mut self, account: &str) -> &mut Self {\n        self.account = Some(CFString::new(account));\n        self\n    }\n\n    /// Search for an item with a specific access group.\n    pub fn access_group(&mut self, access_group: &str) -> &mut Self {\n        self.access_group = Some(CFString::new(access_group));\n        self\n    }\n\n    /// Search for an item based on whether it's cloud-synchronized\n    ///\n    /// If not specified, only searches non-synchronized entries.\n    pub fn cloud_sync<T: Into<CloudSync>>(&mut self, spec: T) -> &mut Self {\n        self.cloud_sync = Some(spec.into());\n        self\n    }\n\n    /// Sets `kSecAttrAccessGroup` to `kSecAttrAccessGroupToken`\n    #[inline(always)]\n    pub fn access_group_token(&mut self) -> &mut Self {\n        self.access_group = unsafe { Some(CFString::wrap_under_get_rule(kSecAttrAccessGroupToken)) };\n        self\n    }\n\n    /// Search for a certificate with the given public key hash.\n    ///\n    /// This is only compatible with [`ItemClass::certificate`], to search for\n    /// a key by public key hash use [`ItemSearchOptions::application_label`]\n    /// instead.\n    #[inline(always)]\n    pub fn pub_key_hash(&mut self, pub_key_hash: &[u8]) -> &mut Self {\n        self.pub_key_hash = Some(CFData::from_buffer(pub_key_hash));\n        self\n    }\n\n    /// Search for a certificate with the given serial number.\n    ///\n    /// This is only compatible with [`ItemClass::certificate`].\n    #[inline(always)]\n    pub fn serial_number(&mut self, serial_number: &[u8]) -> &mut Self {\n        self.serial_number = Some(CFData::from_buffer(serial_number));\n        self\n    }\n\n    /// Search for a key with the given public key hash.\n    ///\n    /// This is only compatible with [`ItemClass::key`], to search for a\n    /// certificate by the public key hash use [`ItemSearchOptions::pub_key_hash`]\n    /// instead.\n    #[inline(always)]\n    pub fn application_label(&mut self, app_label: &[u8]) -> &mut Self {\n        self.app_label = Some(CFData::from_buffer(app_label));\n        self\n    }\n\n    #[doc(hidden)]\n    #[deprecated(note = \"use local_authentication_context\")]\n    pub unsafe fn authentication_context(&mut self, authentication_context: *mut std::os::raw::c_void) -> &mut Self {\n        self.authentication_context = unsafe { Some(CFType::wrap_under_create_rule(authentication_context)) };\n        self\n    }\n\n    /// The corresponding value is of type LAContext, and represents a reusable\n    /// local authentication context that should be used for keychain item authentication.\n    #[inline(always)]\n    pub fn local_authentication_context<LAContext: TCFType>(&mut self, authentication_context: Option<LAContext>) -> &mut Self {\n        self.authentication_context = authentication_context.map(|la| la.into_CFType());\n        self\n    }\n\n    /// Whether to skip items in the search that require authentication (default false)\n    #[inline(always)]\n    pub fn skip_authenticated_items(&mut self, do_skip: bool) -> &mut Self {\n        self.skip_authenticated_items = do_skip;\n        self\n    }\n\n    /// Populates a `CFDictionary` to be passed to `update_item` or `delete_item`.\n    // CFDictionary should not be exposed in public Rust APIs.\n    #[inline]\n    fn to_dictionary(&self) -> CFDictionary {\n        unsafe {\n            let mut params = CFMutableDictionary::from_CFType_pairs(&[]);\n\n            if let Some(keychains) = &self.keychains {\n                params.add(\n                    &kSecMatchSearchList.to_void(),\n                    &keychains.as_CFType().to_void(),\n                );\n            } else if self.ignore_legacy_keychains {\n                #[cfg(all(target_os = \"macos\", feature = \"OSX_10_15\"))]\n                params.add(\n                    &kSecUseDataProtectionKeychain.to_void(),\n                    &CFBoolean::true_value().to_void(),\n                );\n            }\n\n            if let Some(class) = self.class {\n                params.add(&kSecClass.to_void(), &class.0.to_void());\n            }\n\n            if let Some(case_insensitive) = self.case_insensitive {\n                params.add(\n                    &kSecMatchCaseInsensitive.to_void(),\n                    &CFBoolean::from(case_insensitive).to_void(),\n                );\n            }\n\n            if let Some(key_class) = self.key_class {\n                params.add(&kSecAttrKeyClass.to_void(), &key_class.0.to_void());\n            }\n\n            if self.load_refs {\n                params.add(&kSecReturnRef.to_void(), &CFBoolean::true_value().to_void());\n            }\n\n            if self.load_attributes {\n                params.add(\n                    &kSecReturnAttributes.to_void(),\n                    &CFBoolean::true_value().to_void(),\n                );\n            }\n\n            if self.load_data {\n                params.add(\n                    &kSecReturnData.to_void(),\n                    &CFBoolean::true_value().to_void(),\n                );\n            }\n\n            if let Some(limit) = self.limit {\n                params.add(&kSecMatchLimit.to_void(), &limit.to_value().to_void());\n            }\n\n            if let Some(label) = &self.label {\n                params.add(&kSecAttrLabel.to_void(), &label.to_void());\n            }\n\n            if let Some(trusted_only) = &self.trusted_only {\n                params.add(\n                    &kSecMatchTrustedOnly.to_void(),\n                    &CFBoolean::from(*trusted_only).to_void(),\n                );\n            }\n\n            if let Some(service) = &self.service {\n                params.add(&kSecAttrService.to_void(), &service.to_void());\n            }\n\n            #[cfg(target_os = \"macos\")]\n            {\n                if let Some(subject) = &self.subject {\n                    params.add(&kSecMatchSubjectWholeString.to_void(), &subject.to_void());\n                }\n            }\n\n            if let Some(account) = &self.account {\n                params.add(&kSecAttrAccount.to_void(), &account.to_void());\n            }\n\n            if let Some(access_group) = &self.access_group {\n                params.add(&kSecAttrAccessGroup.to_void(), &access_group.to_void());\n            }\n\n            if let Some(cloud_sync) = &self.cloud_sync {\n                match cloud_sync {\n                    CloudSync::MatchSyncYes => {\n                        params.add(&kSecAttrSynchronizable.to_void(), &CFBoolean::true_value().to_void());\n                    },\n                    CloudSync::MatchSyncNo => {\n                        params.add(&kSecAttrSynchronizable.to_void(), &CFBoolean::false_value().to_void());\n                    },\n                    CloudSync::MatchSyncAny => {\n                        params.add(&kSecAttrSynchronizable.to_void(), &kSecAttrSynchronizableAny.to_void());\n                    },\n                }\n            }\n\n            if let Some(pub_key_hash) = &self.pub_key_hash {\n                params.add(&kSecAttrPublicKeyHash.to_void(), &pub_key_hash.to_void());\n            }\n\n            if let Some(serial_number) = &self.serial_number {\n                params.add(&kSecAttrSerialNumber.to_void(), &serial_number.to_void());\n            }\n\n            if let Some(app_label) = &self.app_label {\n                params.add(&kSecAttrApplicationLabel.to_void(), &app_label.to_void());\n            }\n\n            if let Some(authentication_context) = &self.authentication_context {\n                params.add(&kSecUseAuthenticationContext.to_void(), &authentication_context.to_void());\n            }\n\n            if self.skip_authenticated_items {\n                params.add(&kSecUseAuthenticationUI.to_void(), &kSecUseAuthenticationUISkip.to_void());\n            }\n\n            params.to_immutable()\n        }\n    }\n\n    /// Search for objects.\n    #[inline]\n    pub fn search(&self) -> Result<Vec<SearchResult>> {\n        unsafe {\n            let params = self.to_dictionary();\n\n            let mut ret = ptr::null();\n            cvt(SecItemCopyMatching(params.as_concrete_TypeRef(), &mut ret))?;\n            if ret.is_null() {\n                //  SecItemCopyMatching returns NULL if no load_* was specified,\n                //  causing a segfault.\n                return Ok(vec![]);\n            }\n            let type_id = CFGetTypeID(ret);\n\n            let mut items = vec![];\n\n            if type_id == CFArray::<CFType>::type_id() {\n                let array: CFArray<CFType> = CFArray::wrap_under_create_rule(ret as *mut _);\n                for item in array.iter() {\n                    items.push(get_item(item.as_CFTypeRef()));\n                }\n            } else {\n                items.push(get_item(ret));\n                // This is a bit janky, but get_item uses wrap_under_get_rule\n                // which bumps the refcount but we want create semantics\n                CFRelease(ret);\n            }\n\n            Ok(items)\n        }\n    }\n\n    /// Deletes objects matching the search options.\n    ///\n    /// Translates to `SecItemDelete`.\n    #[inline]\n    pub fn delete(&self) -> Result<()> {\n        cvt(unsafe { SecItemDelete(self.to_dictionary().as_concrete_TypeRef()) })\n    }\n}\n\nunsafe fn get_item(item: CFTypeRef) -> SearchResult { unsafe {\n    let type_id = CFGetTypeID(item);\n\n    if type_id == CFData::type_id() {\n        let data = CFData::wrap_under_get_rule(item as *mut _);\n        let mut buf = Vec::new();\n        buf.extend_from_slice(data.bytes());\n        return SearchResult::Data(buf);\n    }\n\n    if type_id == CFDictionary::<*const u8, *const u8>::type_id() {\n        return SearchResult::Dict(CFDictionary::wrap_under_get_rule(item as *mut _));\n    }\n\n    #[cfg(target_os = \"macos\")]\n    {\n        use crate::os::macos::keychain_item::SecKeychainItem;\n        if type_id == SecKeychainItem::type_id() {\n            return SearchResult::Ref(Reference::KeychainItem(\n                SecKeychainItem::wrap_under_get_rule(item as *mut _),\n            ));\n        }\n    }\n\n    let reference = if type_id == SecCertificate::type_id() {\n        Reference::Certificate(SecCertificate::wrap_under_get_rule(item as *mut _))\n    } else if type_id == SecKey::type_id() {\n        Reference::Key(SecKey::wrap_under_get_rule(item as *mut _))\n    } else if type_id == SecIdentity::type_id() {\n        Reference::Identity(SecIdentity::wrap_under_get_rule(item as *mut _))\n    } else {\n        panic!(\"Got bad type from SecItemCopyMatching: {type_id}\");\n    };\n\n    SearchResult::Ref(reference)\n} }\n\n/// An enum including all objects whose references can be returned from a search.\n///\n/// Note that generic _Keychain Items_, such as passwords and preferences, do\n/// not have specific object types; they are modeled using dictionaries and so\n/// are available directly as search results in variant `SearchResult::Dict`.\n#[derive(Debug)]\npub enum Reference {\n    /// A `SecIdentity`.\n    Identity(SecIdentity),\n    /// A `SecCertificate`.\n    Certificate(SecCertificate),\n    /// A `SecKey`.\n    Key(SecKey),\n    /// A `SecKeychainItem`.\n    ///\n    /// Only defined on OSX\n    #[cfg(target_os = \"macos\")]\n    KeychainItem(crate::os::macos::keychain_item::SecKeychainItem),\n    #[doc(hidden)]\n    __NonExhaustive,\n}\n\n/// An individual search result.\npub enum SearchResult {\n    /// A reference to the Security Framework object, if asked for.\n    Ref(Reference),\n    /// A dictionary of data about the Security Framework object, if asked for.\n    Dict(CFDictionary),\n    /// The Security Framework object as bytes, if asked for.\n    Data(Vec<u8>),\n    /// An unknown representation of the Security Framework object.\n    Other,\n}\n\nimpl fmt::Debug for SearchResult {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Self::Ref(reference) => fmt\n                .debug_struct(\"SearchResult::Ref\")\n                .field(\"reference\", reference)\n                .finish(),\n            Self::Data(buf) => fmt\n                .debug_struct(\"SearchResult::Data\")\n                .field(\"data\", buf)\n                .finish(),\n            Self::Dict(_) => {\n                let mut debug = fmt.debug_struct(\"SearchResult::Dict\");\n                for (k, v) in self.simplify_dict().unwrap() {\n                    debug.field(&k, &v);\n                }\n                debug.finish()\n            },\n            Self::Other => write!(fmt, \"SearchResult::Other\"),\n        }\n    }\n}\n\nimpl SearchResult {\n    /// If the search result is a `CFDict`, simplify that to a\n    /// `HashMap<String, String>`. This transformation isn't\n    /// comprehensive, it only supports `CFString`, `CFDate`, and `CFData`\n    /// value types.\n    #[must_use]\n    pub fn simplify_dict(&self) -> Option<HashMap<String, String>> {\n        match self {\n            Self::Dict(d) => unsafe {\n                let mut retmap = HashMap::new();\n                let (keys, values) = d.get_keys_and_values();\n                for (k, v) in keys.iter().zip(values.iter()) {\n                    let keycfstr = CFString::wrap_under_get_rule((*k).cast());\n                    let val: String = match CFGetTypeID(*v) {\n                        cfstring if cfstring == CFString::type_id() => {\n                            format!(\"{}\", CFString::wrap_under_get_rule((*v).cast()))\n                        },\n                        cfdata if cfdata == CFData::type_id() => {\n                            let buf = CFData::wrap_under_get_rule((*v).cast());\n                            let mut vec = Vec::new();\n                            vec.extend_from_slice(buf.bytes());\n                            format!(\"{}\", String::from_utf8_lossy(&vec))\n                        },\n                        cfdate if cfdate == CFDate::type_id() => {\n                            format!(\"{}\", CFString::wrap_under_create_rule(CFCopyDescription(*v)))\n                        },\n                        _ => String::from(\"unknown\"),\n                    };\n                    retmap.insert(format!(\"{keycfstr}\"), val);\n                }\n                Some(retmap)\n            },\n            _ => None,\n        }\n    }\n}\n\n/// Builder-pattern struct for specifying options for `add_item` (`SecAddItem`\n/// wrapper).\n///\n/// When finished populating options call [`Self::add`].\npub struct ItemAddOptions {\n    /// The value (by ref or data) of the item to add, required.\n    pub value: ItemAddValue,\n    /// Optional kSecAttrAccount attribute.\n    pub account_name: Option<CFString>,\n    /// Optional kSecAttrAccessGroup attribute.\n    pub access_group: Option<CFString>,\n    /// Optional kSecAttrComment attribute.\n    pub comment: Option<CFString>,\n    /// Optional kSecAttrDescription attribute.\n    pub description: Option<CFString>,\n    /// Optional kSecAttrLabel attribute.\n    pub label: Option<CFString>,\n    /// Optional kSecAttrService attribute.\n    pub service: Option<CFString>,\n    /// Optional keychain location.\n    pub location: Option<Location>,\n}\n\nimpl ItemAddOptions {\n    /// Specifies the item to add.\n    #[inline]\n    #[must_use]\n    pub fn new(value: ItemAddValue) -> Self {\n        Self {\n            value,\n            label: None,\n            location: None,\n            service: None,\n            account_name: None,\n            comment: None,\n            description: None,\n            access_group: None,\n        }\n    }\n\n    /// Specifies the `kSecAttrAccount` attribute.\n    #[inline]\n    pub fn set_account_name(&mut self, account_name: impl AsRef<str>) -> &mut Self {\n        self.account_name = Some(account_name.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrAccessGroup` attribute.\n    #[inline]\n    pub fn set_access_group(&mut self, access_group: impl AsRef<str>) -> &mut Self {\n        self.access_group = Some(access_group.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrComment` attribute.\n    #[inline]\n    pub fn set_comment(&mut self, comment: impl AsRef<str>) -> &mut Self {\n        self.comment = Some(comment.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrDescription` attribute.\n    #[inline]\n    pub fn set_description(&mut self, description: impl AsRef<str>) -> &mut Self {\n        self.description = Some(description.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrLabel` attribute.\n    #[inline]\n    pub fn set_label(&mut self, label: impl AsRef<str>) -> &mut Self {\n        self.label = Some(label.as_ref().into());\n        self\n    }\n\n    /// Specifies which keychain to add the item to.\n    #[inline]\n    pub fn set_location(&mut self, location: Location) -> &mut Self {\n        self.location = Some(location);\n        self\n    }\n\n    /// Specifies the `kSecAttrService` attribute.\n    #[inline]\n    pub fn set_service(&mut self, service: impl AsRef<str>) -> &mut Self {\n        self.service = Some(service.as_ref().into());\n        self\n    }\n\n    /// Populates a `CFDictionary` to be passed to `add_item`.\n    #[deprecated(since = \"3.0.0\", note = \"use `ItemAddOptions::add` instead\")]\n    // CFDictionary should not be exposed in public Rust APIs.\n    #[must_use]\n    pub fn to_dictionary(&self) -> CFDictionary {\n        let mut dict = CFMutableDictionary::from_CFType_pairs(&[]);\n\n        let class_opt = match &self.value {\n            ItemAddValue::Ref(ref_) => ref_.class(),\n            ItemAddValue::Data { class, .. } => Some(*class),\n        };\n        if let Some(class) = class_opt {\n            dict.add(&unsafe { kSecClass }.to_void(), &class.0.to_void());\n        }\n\n        let value_pair = match &self.value {\n            ItemAddValue::Ref(ref_) => (unsafe { kSecValueRef }.to_void(), ref_.ref_()),\n            ItemAddValue::Data { data, .. } => (unsafe { kSecValueData }.to_void(), data.to_void()),\n        };\n        dict.add(&value_pair.0, &value_pair.1);\n\n        if let Some(location) = &self.location {\n            match location {\n                #[cfg(any(feature = \"OSX_10_15\", not(target_os = \"macos\")))]\n                Location::DataProtectionKeychain => {\n                    dict.add(\n                        &unsafe { kSecUseDataProtectionKeychain }.to_void(),\n                        &CFBoolean::true_value().to_void(),\n                    );\n                }\n                #[cfg(target_os = \"macos\")]\n                Location::DefaultFileKeychain => {},\n                #[cfg(target_os = \"macos\")]\n                Location::FileKeychain(keychain) => {\n                    dict.add(&unsafe { kSecUseKeychain }.to_void(), &keychain.to_void());\n                },\n            }\n        }\n        if let Some(account_name) = &self.account_name {\n            dict.add(&unsafe { kSecAttrAccount }.to_void(), &account_name.to_void());\n        }\n        if let Some(access_group) = &self.access_group {\n            dict.add(&unsafe { kSecAttrAccessGroup }.to_void(), &access_group.to_void());\n        }\n        if let Some(comment) = &self.comment {\n            dict.add(&unsafe { kSecAttrComment }.to_void(), &comment.to_void());\n        }\n        if let Some(description) = &self.description {\n            dict.add(&unsafe { kSecAttrDescription }.to_void(), &description.to_void());\n        }\n        if let Some(label) = &self.label {\n            dict.add(&unsafe { kSecAttrLabel }.to_void(), &label.to_void());\n        }\n        if let Some(service) = &self.service {\n            dict.add(&unsafe { kSecAttrService }.to_void(), &service.to_void());\n        }\n\n        dict.to_immutable()\n    }\n\n    /// Adds the item to the keychain.\n    ///\n    /// Translates to `SecItemAdd`.\n    #[inline]\n    pub fn add(&self) -> Result<()> {\n        #[allow(deprecated)]\n        cvt(unsafe { SecItemAdd(self.to_dictionary().as_concrete_TypeRef(), std::ptr::null_mut()) })\n    }\n}\n\n/// Value of an item to add to the keychain.\npub enum ItemAddValue {\n    /// Pass item by Ref (kSecValueRef)\n    Ref(AddRef),\n    /// Pass item by Data (kSecValueData)\n    Data {\n        /// The item class (kSecClass).\n        class: ItemClass,\n        /// The item data.\n        data: CFData,\n    },\n}\n\n/// Type of Ref to add to the keychain.\npub enum AddRef {\n    /// `SecKey`\n    Key(SecKey),\n    /// `SecIdentity`\n    Identity(SecIdentity),\n    /// `SecCertificate`\n    Certificate(SecCertificate),\n}\n\nimpl AddRef {\n    fn class(&self) -> Option<ItemClass> {\n        match self {\n            Self::Key(_) => Some(ItemClass::key()),\n            //  kSecClass should not be specified when adding a SecIdentityRef:\n            //  https://developer.apple.com/forums/thread/25751\n            Self::Identity(_) => None,\n            Self::Certificate(_) => Some(ItemClass::certificate()),\n        }\n    }\n\n    fn ref_(&self) -> CFTypeRef {\n        match self {\n            Self::Key(key) => key.as_CFTypeRef(),\n            Self::Identity(id) => id.as_CFTypeRef(),\n            Self::Certificate(cert) => cert.as_CFTypeRef(),\n        }\n    }\n}\n\n/// Builder-pattern struct for specifying options for `update_item` (`SecUpdateItem`\n/// wrapper).\n///\n/// When finished populating options call [`update_item`].\n#[derive(Default)]\npub struct ItemUpdateOptions {\n    /// Optional value (by ref or data) of the item to update.\n    pub value: Option<ItemUpdateValue>,\n    /// Optional kSecAttrAccount attribute.\n    pub account_name: Option<CFString>,\n    /// Optional kSecAttrAccessGroup attribute.\n    pub access_group: Option<CFString>,\n    /// Optional kSecAttrComment attribute.\n    pub comment: Option<CFString>,\n    /// Optional kSecAttrDescription attribute.\n    pub description: Option<CFString>,\n    /// Optional kSecAttrLabel attribute.\n    pub label: Option<CFString>,\n    /// Optional kSecAttrService attribute.\n    pub service: Option<CFString>,\n    /// Optional keychain location.\n    pub location: Option<Location>,\n    /// Optional kSecClass.\n    ///\n    /// Overwrites `value`'s class if set.\n    pub class: Option<ItemClass>,\n}\n\nimpl ItemUpdateOptions {\n    /// Specifies the item to add.\n    #[must_use]\n    pub fn new() -> Self {\n        Default::default()\n    }\n\n    /// Specifies the value of the item.\n    #[inline]\n    pub fn set_value(&mut self, value: ItemUpdateValue) -> &mut Self {\n        self.value = Some(value);\n        self\n    }\n\n    /// Specifies the `kSecClass` attribute.\n    #[inline]\n    pub fn set_class(&mut self, class: ItemClass) -> &mut Self {\n        self.class = Some(class);\n        self\n    }\n\n    /// Specifies the `kSecAttrAccount` attribute.\n    #[inline]\n    pub fn set_account_name(&mut self, account_name: impl AsRef<str>) -> &mut Self {\n        self.account_name = Some(account_name.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrAccessGroup` attribute.\n    #[inline]\n    pub fn set_access_group(&mut self, access_group: impl AsRef<str>) -> &mut Self {\n        self.access_group = Some(access_group.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrComment` attribute.\n    #[inline]\n    pub fn set_comment(&mut self, comment: impl AsRef<str>) -> &mut Self {\n        self.comment = Some(comment.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrDescription` attribute.\n    #[inline]\n    pub fn set_description(&mut self, description: impl AsRef<str>) -> &mut Self {\n        self.description = Some(description.as_ref().into());\n        self\n    }\n\n    /// Specifies the `kSecAttrLabel` attribute.\n    #[inline]\n    pub fn set_label(&mut self, label: impl AsRef<str>) -> &mut Self {\n        self.label = Some(label.as_ref().into());\n        self\n    }\n\n    /// Specifies which keychain to add the item to.\n    #[inline]\n    pub fn set_location(&mut self, location: Location) -> &mut Self {\n        self.location = Some(location);\n        self\n    }\n\n    /// Specifies the `kSecAttrService` attribute.\n    #[inline]\n    pub fn set_service(&mut self, service: impl AsRef<str>) -> &mut Self {\n        self.service = Some(service.as_ref().into());\n        self\n    }\n\n    /// Populates a `CFDictionary` to be passed to `update_item`.\n    // CFDictionary should not be exposed in public Rust APIs.\n    #[inline]\n    fn to_dictionary(&self) -> CFDictionary {\n        let mut dict = CFMutableDictionary::from_CFType_pairs(&[]);\n\n        if let Some(value) = &self.value {\n            let class_opt = match value {\n                ItemUpdateValue::Ref(ref_) => ref_.class(),\n                ItemUpdateValue::Data(_) => None,\n            };\n            // `self.class` overwrites `value`'s class if set.\n            if self.class.is_none() {\n                if let Some(class) = class_opt {\n                    dict.add(&unsafe { kSecClass }.to_void(), &class.0.to_void());\n                }\n            }\n            let value_pair = match value {\n                ItemUpdateValue::Ref(ref_) => (unsafe { kSecValueRef }.to_void(), ref_.ref_()),\n                ItemUpdateValue::Data(data) => (unsafe { kSecValueData }.to_void(), data.to_void()),\n            };\n            dict.add(&value_pair.0, &value_pair.1);\n        }\n        if let Some(class) = self.class {\n            dict.add(&unsafe { kSecClass }.to_void(), &class.0.to_void());\n        }\n        if let Some(location) = &self.location {\n            match location {\n                #[cfg(any(feature = \"OSX_10_15\", not(target_os = \"macos\")))]\n                Location::DataProtectionKeychain => {\n                    dict.add(\n                        &unsafe { kSecUseDataProtectionKeychain }.to_void(),\n                        &CFBoolean::true_value().to_void(),\n                    );\n                }\n                #[cfg(target_os = \"macos\")]\n                Location::DefaultFileKeychain => {},\n                #[cfg(target_os = \"macos\")]\n                Location::FileKeychain(keychain) => {\n                    dict.add(&unsafe { kSecUseKeychain }.to_void(), &keychain.to_void());\n                },\n            }\n        }\n        if let Some(account_name) = &self.account_name {\n            dict.add(&unsafe { kSecAttrAccount }.to_void(), &account_name.to_void());\n        }\n        if let Some(access_group) = &self.access_group {\n            dict.add(&unsafe { kSecAttrAccessGroup }.to_void(), &access_group.to_void());\n        }\n        if let Some(comment) = &self.comment {\n            dict.add(&unsafe { kSecAttrComment }.to_void(), &comment.to_void());\n        }\n        if let Some(description) = &self.description {\n            dict.add(&unsafe { kSecAttrDescription }.to_void(), &description.to_void());\n        }\n        if let Some(label) = &self.label {\n            dict.add(&unsafe { kSecAttrLabel }.to_void(), &label.to_void());\n        }\n        if let Some(service) = &self.service {\n            dict.add(&unsafe { kSecAttrService }.to_void(), &service.to_void());\n        }\n\n        dict.to_immutable()\n    }\n}\n\n/// Value of an item to update in the keychain.\npub enum ItemUpdateValue {\n    /// Pass item by Ref (kSecValueRef)\n    Ref(AddRef),\n    /// Pass item by Data (kSecValueData)\n    ///\n    /// Note that if the [`ItemClass`] of the updated data is different to the original data\n    /// stored in the keychain, it should be specified using [`ItemUpdateOptions::set_class`].\n    Data(CFData),\n}\n\n/// Which keychain to add an item to.\n///\n/// <https://developer.apple.com/documentation/technotes/tn3137-on-mac-keychains>\npub enum Location {\n    /// Store the item in the newer `DataProtectionKeychain`. This is the only\n    /// keychain on iOS. On macOS, this is the newer and more consistent\n    /// keychain implementation. Keys stored in the Secure Enclave _must_ use\n    /// this keychain.\n    ///\n    /// This keychain requires the calling binary to be codesigned with\n    /// entitlements for the `KeychainAccessGroups` it is supposed to\n    /// access.\n    #[cfg(any(feature = \"OSX_10_15\", not(target_os = \"macos\")))]\n    DataProtectionKeychain,\n    /// Store the key in the default file-based keychain. On macOS, defaults to\n    /// the Login keychain.\n    #[cfg(target_os = \"macos\")]\n    DefaultFileKeychain,\n    /// Store the key in a specific file-based keychain.\n    #[cfg(target_os = \"macos\")]\n    FileKeychain(crate::os::macos::keychain::SecKeychain),\n}\n\nimpl fmt::Debug for Location {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(match self {\n            #[cfg(any(feature = \"OSX_10_15\", not(target_os = \"macos\")))]\n            Self::DataProtectionKeychain => \"DataProtectionKeychain\",\n            #[cfg(target_os = \"macos\")]\n            Self::DefaultFileKeychain => \"DefaultFileKeychain\",\n            #[cfg(target_os = \"macos\")]\n            Self::FileKeychain(_) => \"FileKeychain\",\n        })\n    }\n}\n\n/// Translates to `SecItemAdd`. Use `ItemAddOptions` to build an `add_params`\n/// `CFDictionary`.\n#[deprecated(since = \"3.0.0\", note = \"use `ItemAddOptions::add` instead\")]\n#[allow(deprecated)]\npub fn add_item(add_params: CFDictionary) -> Result<()> {\n    cvt(unsafe { SecItemAdd(add_params.as_concrete_TypeRef(), std::ptr::null_mut()) })\n}\n\n/// Translates to `SecItemUpdate`.\npub fn update_item(search_params: &ItemSearchOptions, update_params: &ItemUpdateOptions) -> Result<()> {\n    cvt(unsafe { SecItemUpdate(\n        search_params.to_dictionary().as_concrete_TypeRef(),\n        update_params.to_dictionary().as_concrete_TypeRef()\n    )})\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n\n    #[test]\n    fn find_nothing() {\n        assert!(ItemSearchOptions::new().search().is_err());\n    }\n\n    #[test]\n    fn limit_two() {\n        let results = ItemSearchOptions::new()\n            .class(ItemClass::certificate())\n            .limit(2)\n            .search()\n            .unwrap();\n        assert_eq!(results.len(), 2);\n    }\n\n    #[test]\n    fn limit_all() {\n        let results = ItemSearchOptions::new()\n            .class(ItemClass::certificate())\n            .limit(Limit::All)\n            .search()\n            .unwrap();\n        assert!(results.len() >= 2);\n    }\n}\n"
  },
  {
    "path": "security-framework/src/key.rs",
    "content": "//! Encryption key support\n\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse crate::cvt;\nuse core_foundation::{\n    base::TCFType, string::{CFStringRef, CFString},\n    dictionary::CFMutableDictionary,\n};\nuse core_foundation::base::ToVoid;\nuse core_foundation::boolean::CFBoolean;\nuse core_foundation::data::CFData;\nuse core_foundation::dictionary::CFDictionary;\nuse core_foundation::number::CFNumber;\nuse core_foundation::error::{CFError, CFErrorRef};\n\nuse security_framework_sys::item::{kSecAttrIsPermanent, kSecAttrLabel, kSecAttrKeyType, kSecAttrKeySizeInBits, kSecAttrAccessControl};\n#[allow(deprecated)]\nuse security_framework_sys::item::{kSecAttrKeyTypeEC, kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyTypeRSA, kSecValueRef};\nuse security_framework_sys::keychain_item::SecItemDelete;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::item::{\n    kSecAttrKeyType3DES, kSecAttrKeyTypeDSA, kSecAttrKeyTypeAES,\n    kSecAttrKeyTypeDES, kSecAttrKeyTypeRC4, kSecAttrKeyTypeCAST,\n};\n\nuse security_framework_sys::base::SecKeyRef;\nuse security_framework_sys::key::SecKeyGetTypeID;\n\npub use security_framework_sys::key::Algorithm;\n\nuse security_framework_sys::key::{\n    SecKeyCopyAttributes, SecKeyCopyExternalRepresentation,\n    SecKeyCreateSignature, SecKeyCreateRandomKey,\n    SecKeyCopyPublicKey,\n    SecKeyCreateDecryptedData, SecKeyCreateEncryptedData,\n};\nuse security_framework_sys::item::kSecAttrApplicationLabel;\nuse std::fmt;\n\n\nuse crate::base::Error;\nuse crate::item::Location;\nuse crate::access_control::SecAccessControl;\n/// Types of `SecKey`s.\n#[derive(Debug, Copy, Clone, PartialEq)]\npub struct KeyType(CFStringRef);\n\n#[allow(missing_docs)]\nimpl KeyType {\n    #[inline(always)]\n    #[must_use]\n    pub fn rsa() -> Self {\n        unsafe { Self(kSecAttrKeyTypeRSA) }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    #[must_use]\n    pub fn dsa() -> Self {\n        unsafe { Self(kSecAttrKeyTypeDSA) }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    #[must_use]\n    pub fn aes() -> Self {\n        unsafe { Self(kSecAttrKeyTypeAES) }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    #[must_use]\n    pub fn des() -> Self {\n        unsafe { Self(kSecAttrKeyTypeDES) }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    #[must_use]\n    pub fn triple_des() -> Self {\n        unsafe { Self(kSecAttrKeyType3DES) }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    #[must_use]\n    pub fn rc4() -> Self {\n        unsafe { Self(kSecAttrKeyTypeRC4) }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    #[inline(always)]\n    #[must_use]\n    pub fn cast() -> Self {\n        unsafe { Self(kSecAttrKeyTypeCAST) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    #[allow(deprecated)]\n    #[deprecated(note = \"deprecated by Apple\")]\n    pub fn ec() -> Self {\n        unsafe { Self(kSecAttrKeyTypeEC) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn ec_sec_prime_random() -> Self {\n        unsafe { Self(kSecAttrKeyTypeECSECPrimeRandom) }\n    }\n\n    pub(crate) fn as_cfstring(self) -> CFStringRef {\n        self.0\n    }\n\n    /// Assumed based on the key type\n    pub fn default_size_in_bits(&self) -> Option<u32> {\n        #[cfg(target_os = \"macos\")]\n        unsafe {\n            if self.0 == kSecAttrKeyTypeAES {\n                return Some(256);\n            } else if self.0 == kSecAttrKeyTypeDES {\n                return Some(64);\n            } else if self.0 == kSecAttrKeyType3DES {\n                return Some(192);\n            } else if self.0 == kSecAttrKeyTypeRC4 {\n                return Some(128);\n            } else if self.0 == kSecAttrKeyTypeCAST {\n                return Some(128);\n            } else if self.0 == kSecAttrKeyTypeDSA {\n                return Some(2048);\n            }\n        }\n        #[allow(deprecated)]\n        unsafe {\n            if self.0 == kSecAttrKeyTypeRSA {\n                Some(2048)\n            } else if self.0 == kSecAttrKeyTypeEC {\n                Some(256)\n            } else if self.0 == kSecAttrKeyTypeECSECPrimeRandom {\n                Some(256)\n            } else {\n                None\n            }\n        }\n    }\n}\n\ndeclare_TCFType! {\n    /// A type representing an encryption key.\n    SecKey, SecKeyRef\n}\nimpl_TCFType!(SecKey, SecKeyRef, SecKeyGetTypeID);\n\nunsafe impl Sync for SecKey {}\nunsafe impl Send for SecKey {}\n\nimpl SecKey {\n    /// Translates to `SecKeyCreateRandomKey`\n    #[allow(deprecated)]\n    #[doc(alias = \"SecKeyCreateRandomKey\")]\n    pub fn new(options: &GenerateKeyOptions) -> Result<Self, CFError> {\n        Self::generate(options.to_dictionary())\n    }\n\n    /// Translates to `SecKeyCreateRandomKey`\n    /// `GenerateKeyOptions` provides a helper to create an attribute `CFDictionary`.\n    #[deprecated(note = \"Use SecKey::new\")]\n    pub fn generate(attributes: CFDictionary) -> Result<Self, CFError> {\n        let mut error: CFErrorRef = ::std::ptr::null_mut();\n        let sec_key = unsafe { SecKeyCreateRandomKey(attributes.as_concrete_TypeRef(), &mut error) };\n        if error.is_null() {\n            Ok(unsafe { Self::wrap_under_create_rule(sec_key) })\n        } else {\n            Err(unsafe { CFError::wrap_under_create_rule(error) })\n        }\n    }\n\n    /// Returns the programmatic identifier for the key. For keys of class\n    /// kSecAttrKeyClassPublic and kSecAttrKeyClassPrivate, the value is the\n    /// hash of the public key.\n    #[must_use]\n    pub fn application_label(&self) -> Option<Vec<u8>> {\n        self.attributes()\n            .find(unsafe { kSecAttrApplicationLabel.to_void() })\n            .map(|v| unsafe { CFData::wrap_under_get_rule(v.cast()) }.to_vec())\n    }\n\n    /// Translates to `SecKeyCopyAttributes`\n    // TODO: deprecate and remove. CFDictionary should not be exposed in public Rust APIs.\n    #[must_use]\n    pub fn attributes(&self) -> CFDictionary {\n        let pka = unsafe { SecKeyCopyAttributes(self.to_void() as _) };\n        unsafe { CFDictionary::wrap_under_create_rule(pka) }\n    }\n\n    /// Translates to `SecKeyCopyExternalRepresentation`\n    // TODO: deprecate and remove. CFData should not be exposed in public Rust APIs.\n    #[must_use]\n    pub fn external_representation(&self) -> Option<CFData> {\n        let mut error: CFErrorRef = ::std::ptr::null_mut();\n        let data = unsafe { SecKeyCopyExternalRepresentation(self.to_void() as _, &mut error) };\n        if data.is_null() {\n            return None;\n        }\n        Some(unsafe { CFData::wrap_under_create_rule(data) })\n    }\n\n    /// Translates to `SecKeyCopyPublicKey`\n    #[must_use]\n    pub fn public_key(&self) -> Option<Self> {\n        let pub_seckey = unsafe { SecKeyCopyPublicKey(self.0.cast()) };\n        if pub_seckey.is_null() {\n            return None;\n        }\n\n        Some(unsafe { Self::wrap_under_create_rule(pub_seckey) })\n    }\n\n    /// Encrypts a block of data using a public key and specified algorithm\n    pub fn encrypt_data(&self, algorithm: Algorithm, input: &[u8]) -> Result<Vec<u8>, CFError> {\n        let mut error: CFErrorRef = std::ptr::null_mut();\n\n        let output = unsafe {\n            SecKeyCreateEncryptedData(self.as_concrete_TypeRef(), algorithm.into(), CFData::from_buffer(input).as_concrete_TypeRef(), &mut error)\n        };\n\n        if error.is_null() {\n            let output = unsafe { CFData::wrap_under_create_rule(output) };\n            Ok(output.to_vec())\n        } else {\n            Err(unsafe { CFError::wrap_under_create_rule(error) })\n        }\n    }\n\n    /// Decrypts a block of data using a private key and specified algorithm\n    pub fn decrypt_data(&self, algorithm: Algorithm, input: &[u8]) -> Result<Vec<u8>, CFError> {\n        let mut error: CFErrorRef = std::ptr::null_mut();\n\n        let output = unsafe {\n            SecKeyCreateDecryptedData(self.as_concrete_TypeRef(), algorithm.into(), CFData::from_buffer(input).as_concrete_TypeRef(), &mut error)\n        };\n\n        if error.is_null() {\n            let output = unsafe { CFData::wrap_under_create_rule(output) };\n            Ok(output.to_vec())\n        } else {\n            Err(unsafe { CFError::wrap_under_create_rule(error) })\n        }\n    }\n\n    /// Creates the cryptographic signature for a block of data using a private\n    /// key and specified algorithm.\n    pub fn create_signature(&self, algorithm: Algorithm, input: &[u8]) -> Result<Vec<u8>, CFError> {\n        let mut error: CFErrorRef = std::ptr::null_mut();\n\n        let output = unsafe {\n            SecKeyCreateSignature(\n                self.as_concrete_TypeRef(),\n                algorithm.into(),\n                CFData::from_buffer(input).as_concrete_TypeRef(),\n                &mut error,\n            )\n        };\n\n        if error.is_null() {\n            let output = unsafe { CFData::wrap_under_create_rule(output) };\n            Ok(output.to_vec())\n        } else {\n            Err(unsafe { CFError::wrap_under_create_rule(error) })\n        }\n    }\n\n    /// Verifies the cryptographic signature for a block of data using a public\n    /// key and specified algorithm.\n    pub fn verify_signature(&self, algorithm: Algorithm, signed_data: &[u8], signature: &[u8]) -> Result<bool, CFError> {\n        use security_framework_sys::key::SecKeyVerifySignature;\n        let mut error: CFErrorRef = std::ptr::null_mut();\n\n        let valid = unsafe {\n            SecKeyVerifySignature(\n                self.as_concrete_TypeRef(),\n                algorithm.into(),\n                CFData::from_buffer(signed_data).as_concrete_TypeRef(),\n                CFData::from_buffer(signature).as_concrete_TypeRef(),\n                &mut error,\n            )\n        };\n\n        if !error.is_null() {\n            return Err(unsafe { CFError::wrap_under_create_rule(error) })?;\n        }\n        Ok(valid != 0)\n    }\n\n    /// Performs the Diffie-Hellman style of key exchange.\n    pub fn key_exchange(\n        &self,\n        algorithm: Algorithm,\n        public_key: &Self,\n        requested_size: usize,\n        shared_info: Option<&[u8]>,\n    ) -> Result<Vec<u8>, CFError> {\n        use core_foundation::data::CFData;\n        use security_framework_sys::item::{\n            kSecKeyKeyExchangeParameterRequestedSize, kSecKeyKeyExchangeParameterSharedInfo,\n        };\n\n        unsafe {\n            let mut params = vec![(\n                CFString::wrap_under_get_rule(kSecKeyKeyExchangeParameterRequestedSize),\n                CFNumber::from(requested_size as i64).into_CFType(),\n            )];\n\n            if let Some(shared_info) = shared_info {\n                params.push((\n                    CFString::wrap_under_get_rule(kSecKeyKeyExchangeParameterSharedInfo),\n                    CFData::from_buffer(shared_info).as_CFType(),\n                ));\n            }\n\n            let parameters = CFDictionary::from_CFType_pairs(&params);\n\n            let mut error: CFErrorRef = std::ptr::null_mut();\n\n            let output = security_framework_sys::key::SecKeyCopyKeyExchangeResult(\n                self.as_concrete_TypeRef(),\n                algorithm.into(),\n                public_key.as_concrete_TypeRef(),\n                parameters.as_concrete_TypeRef(),\n                &mut error,\n            );\n\n            if error.is_null() {\n                let output = CFData::wrap_under_create_rule(output);\n                Ok(output.to_vec())\n            } else {\n                Err(CFError::wrap_under_create_rule(error))\n            }\n        }\n    }\n\n    /// Translates to `SecItemDelete`, passing in the `SecKeyRef`\n    pub fn delete(&self) -> Result<(), Error> {\n        let query = CFMutableDictionary::from_CFType_pairs(&[(\n            unsafe { kSecValueRef }.to_void(),\n            self.to_void(),\n        )]);\n\n        cvt(unsafe { SecItemDelete(query.as_concrete_TypeRef()) })\n    }\n}\n\n/// Where to generate the key.\n#[derive(Debug)]\npub enum Token {\n    /// Generate the key in software, compatible with all `KeyType`s.\n    Software,\n    /// Generate the key in the Secure Enclave such that the private key is not\n    /// extractable. Only compatible with `KeyType::ec()`.\n    SecureEnclave,\n}\n\n/// Helper for creating `CFDictionary` attributes for `SecKey::generate`\n/// Recommended reading:\n/// <https://developer.apple.com/documentation/technotes/tn3137-on-mac-keychains>\n#[derive(Debug, Default)]\npub struct GenerateKeyOptions {\n    /// kSecAttrKeyType\n    #[deprecated(note = \"use set_key_type()\")]\n    pub key_type: Option<KeyType>,\n    /// kSecAttrKeySizeInBits\n    #[deprecated(note = \"use set_size_in_bits()\")]\n    pub size_in_bits: Option<u32>,\n    /// kSecAttrLabel\n    #[deprecated(note = \"use set_label()\")]\n    pub label: Option<String>,\n    /// kSecAttrTokenID\n    #[deprecated(note = \"use set_token()\")]\n    pub token: Option<Token>,\n    /// Which keychain to store the key in, if any.\n    #[deprecated(note = \"use set_location()\")]\n    pub location: Option<Location>,\n    /// Access control\n    #[deprecated(note = \"use set_access_control()\")]\n    pub access_control: Option<SecAccessControl>,\n    /// `kSecAttrSynchronizable`\n    #[cfg(feature = \"sync-keychain\")]\n    synchronizable: Option<bool>,\n}\n\n#[allow(deprecated)]\nimpl GenerateKeyOptions {\n    /// `kSecAttrKeyType`\n    pub fn set_key_type(&mut self, key_type: KeyType) -> &mut Self {\n        self.key_type = Some(key_type);\n        self\n    }\n\n    /// `kSecAttrKeySizeInBits`\n    pub fn set_size_in_bits(&mut self, size_in_bits: u32) -> &mut Self {\n        self.size_in_bits = Some(size_in_bits);\n        self\n    }\n\n    /// `kSecAttrLabel`\n    pub fn set_label(&mut self, label: impl Into<String>) -> &mut Self {\n        self.label = Some(label.into());\n        self\n    }\n\n    /// `kSecAttrTokenID`\n    pub fn set_token(&mut self, token: Token) -> &mut Self {\n        self.token = Some(token);\n        self\n    }\n\n    /// Which keychain to store the key in, if any.\n    pub fn set_location(&mut self, location: Location) -> &mut Self {\n        self.location = Some(location);\n        self\n    }\n\n    /// Set `access_control`\n    pub fn set_access_control(&mut self, access_control: SecAccessControl) -> &mut Self {\n        self.access_control = Some(access_control);\n        self\n    }\n\n    /// Set `synchronizable` (`kSecAttrSynchronizable`)\n    #[cfg(feature = \"sync-keychain\")]\n    pub fn set_synchronizable(&mut self, synchronizable: bool) -> &mut Self {\n        self.synchronizable = Some(synchronizable);\n        self\n    }\n\n    /// Collect options into a `CFDictioanry`\n    // CFDictionary should not be exposed in public Rust APIs.\n    #[deprecated(note = \"Pass the options to SecKey::new\")]\n    pub fn to_dictionary(&self) -> CFDictionary {\n        use security_framework_sys::item::{kSecAttrTokenID, kSecAttrTokenIDSecureEnclave};\n\n        let is_permanent = CFBoolean::from(self.location.is_some());\n        let mut private_attributes = CFMutableDictionary::from_CFType_pairs(&[(\n            unsafe { kSecAttrIsPermanent }.to_void(),\n            is_permanent.to_void(),\n        )]);\n        if let Some(access_control) = &self.access_control {\n            private_attributes.set(unsafe { kSecAttrAccessControl }.to_void(), access_control.to_void());\n        }\n\n        #[cfg(target_os = \"macos\")]\n        let public_attributes = CFMutableDictionary::from_CFType_pairs(&[(\n            unsafe { kSecAttrIsPermanent }.to_void(),\n            is_permanent.to_void(),\n        )]);\n\n        let key_type = self.key_type.unwrap_or_else(KeyType::rsa);\n        let key_type_str = key_type.as_cfstring();\n\n        let size_in_bits = self.size_in_bits.unwrap_or(key_type.default_size_in_bits().unwrap_or(256));\n        let size_in_bits = CFNumber::from(size_in_bits as i32);\n\n        let mut attribute_key_values = vec![\n            (unsafe { kSecAttrKeyType }.to_void(), key_type_str.to_void()),\n            (unsafe { kSecAttrKeySizeInBits }.to_void(), size_in_bits.to_void()),\n        ];\n        #[cfg(target_os = \"macos\")]\n        if key_type != KeyType::aes() {\n            attribute_key_values.push((unsafe { security_framework_sys::item::kSecPublicKeyAttrs }.to_void(), public_attributes.to_void()));\n            attribute_key_values.push((unsafe { security_framework_sys::item::kSecPrivateKeyAttrs }.to_void(), private_attributes.to_void()));\n        } else {\n            attribute_key_values.push((unsafe { security_framework_sys::item::kSecAttrCanEncrypt }.to_void(), CFBoolean::true_value().to_void()));\n            attribute_key_values.push((unsafe { security_framework_sys::item::kSecAttrCanDecrypt }.to_void(), CFBoolean::true_value().to_void()));\n        }\n\n        let label = self.label.as_deref().map(CFString::new);\n        if let Some(label) = &label {\n            attribute_key_values.push((unsafe { kSecAttrLabel }.to_void(), label.to_void()));\n        }\n\n        #[cfg(target_os = \"macos\")]\n        match &self.location {\n            #[cfg(feature = \"OSX_10_15\")]\n            Some(Location::DataProtectionKeychain) => {\n                use security_framework_sys::item::kSecUseDataProtectionKeychain;\n                attribute_key_values.push((\n                    unsafe { kSecUseDataProtectionKeychain }.to_void(),\n                    CFBoolean::true_value().to_void(),\n                ));\n            }\n            Some(Location::FileKeychain(keychain)) => {\n                attribute_key_values.push((\n                    unsafe { security_framework_sys::item::kSecUseKeychain }.to_void(),\n                    keychain.as_concrete_TypeRef().to_void(),\n                ));\n            },\n            _ => {},\n        }\n\n        match self.token.as_ref().unwrap_or(&Token::Software) {\n            Token::Software => {},\n            Token::SecureEnclave => {\n                attribute_key_values.push((\n                    unsafe { kSecAttrTokenID }.to_void(),\n                    unsafe { kSecAttrTokenIDSecureEnclave }.to_void(),\n                ));\n            }\n        }\n\n        #[cfg(feature = \"sync-keychain\")]\n        if let Some(synchronizable) = &self.synchronizable {\n            attribute_key_values.push((\n                unsafe { security_framework_sys::item::kSecAttrSynchronizable }.to_void(),\n                CFBoolean::from(*synchronizable).to_void(),\n            ));\n        }\n\n        CFMutableDictionary::from_CFType_pairs(&attribute_key_values).to_immutable()\n    }\n}\n\nimpl fmt::Debug for SecKey {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"SecKey\").finish_non_exhaustive()\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::{KeyType, SecKey, GenerateKeyOptions};\n\n    #[test]\n    #[cfg(target_os = \"macos\")]\n    fn generate_aes_key() {\n        let key = SecKey::new(&GenerateKeyOptions::default()\n            .set_key_type(KeyType::aes())\n            .set_size_in_bits(256)).expect(\"Failed to generate AES key\");\n\n        // Verify the key has attributes\n        let attrs = key.attributes();\n        assert!(!attrs.is_empty(), \"AES key should have attributes\");\n    }\n}\n"
  },
  {
    "path": "security-framework/src/lib.rs",
    "content": "#![cfg(target_vendor = \"apple\")]\n\n//! Wrappers around the macOS Security Framework.\n#![warn(missing_docs)]\n#![allow(non_upper_case_globals)]\n#![allow(clippy::manual_non_exhaustive)] // MSRV\n#![allow(clippy::bad_bit_mask)] // bitflags\n#![allow(clippy::struct_excessive_bools)]\n#![allow(clippy::unreadable_literal)]\n#![allow(clippy::ignore_without_reason)]\n\nuse core_foundation_sys::base::OSStatus;\nuse security_framework_sys::base::errSecSuccess;\n\nuse crate::base::{Error, Result};\n\n#[cfg(test)]\nmacro_rules! p {\n    ($e:expr) => {\n        match $e {\n            Ok(s) => s,\n            Err(e) => panic!(\"{:?}\", e),\n        }\n    };\n}\n\npub mod access_control;\n#[cfg(target_os = \"macos\")]\npub mod authorization;\npub mod base;\npub mod certificate;\npub mod cipher_suite;\n#[cfg(target_os = \"macos\")]\npub mod cms;\npub mod identity;\npub mod import_export;\npub mod item;\npub mod key;\npub mod os;\npub mod passwords;\n#[doc(hidden)]\npub mod passwords_options;\npub mod policy;\npub mod random;\npub mod secure_transport;\npub mod trust;\n#[cfg(target_os = \"macos\")]\npub mod trust_settings;\n\n#[inline(always)]\nfn cvt(err: OSStatus) -> Result<()> {\n    match err {\n        errSecSuccess => Ok(()),\n        err => Err(Error::from_code(err)),\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use crate::certificate::SecCertificate;\n\n    /// Returns the server certificate (for certificate parsing/identity tests)\n    pub fn certificate() -> SecCertificate {\n        let certificate = include_bytes!(\"../test/server.der\");\n        p!(SecCertificate::from_der(certificate))\n    }\n\n    /// Returns the CA certificate (trust anchor for TLS verification)\n    pub fn ca_certificate() -> SecCertificate {\n        let certificate = include_bytes!(\"../test/ca.der\");\n        p!(SecCertificate::from_der(certificate))\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/access.rs",
    "content": "#![allow(deprecated)]\n//! Access functionality.\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse security_framework_sys::access::SecAccessGetTypeID;\nuse security_framework_sys::base::SecAccessRef;\n\ndeclare_TCFType! {\n    /// A type representing access settings.\n    SecAccess, SecAccessRef\n}\nimpl_TCFType!(SecAccess, SecAccessRef, SecAccessGetTypeID);\n\nunsafe impl Sync for SecAccess {}\nunsafe impl Send for SecAccess {}\n"
  },
  {
    "path": "security-framework/src/os/macos/certificate.rs",
    "content": "//! OSX specific extensions to certificate functionality.\n\nuse core_foundation::array::{CFArray, CFArrayIterator};\nuse core_foundation::base::{TCFType, ToVoid};\nuse core_foundation::data::CFData;\nuse core_foundation::dictionary::CFDictionary;\nuse core_foundation::error::CFError;\nuse core_foundation::string::CFString;\nuse security_framework_sys::certificate::*;\nuse std::ptr;\n\nuse crate::base::Error;\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::key::SecKey;\nuse crate::os::macos::certificate_oids::CertificateOid;\n#[allow(deprecated)]\nuse crate::os::macos::digest_transform::{Builder, DigestType};\n\n/// An extension trait adding OSX specific functionality to `SecCertificate`.\npub trait SecCertificateExt {\n    /// Returns the common name associated with the certificate.\n    fn common_name(&self) -> Result<String, Error>;\n\n    /// Returns the public key associated with the certificate.\n    fn public_key(&self) -> Result<SecKey, Error>;\n\n    /// Returns the set of properties associated with the certificate.\n    ///\n    /// The `keys` argument can optionally be used to filter the properties loaded to an explicit\n    /// subset.\n    fn properties(&self, keys: Option<&[CertificateOid]>) -> Result<CertificateProperties, CFError>;\n\n    /// Returns the SHA-256 fingerprint of the certificate.\n    fn fingerprint(&self) -> Result<[u8; 32], CFError> { unimplemented!() }\n}\n\nimpl SecCertificateExt for SecCertificate {\n    fn common_name(&self) -> Result<String, Error> {\n        unsafe {\n            let mut string = ptr::null();\n            cvt(SecCertificateCopyCommonName(self.as_concrete_TypeRef(), &mut string))?;\n            Ok(CFString::wrap_under_create_rule(string).to_string())\n        }\n    }\n\n    fn public_key(&self) -> Result<SecKey, Error> {\n        unsafe {\n            let key = SecCertificateCopyKey(self.as_concrete_TypeRef());\n            if key.is_null() {\n                return Err(Error::from_code(-26275));\n            }\n            Ok(SecKey::wrap_under_create_rule(key))\n        }\n    }\n\n    fn properties(&self, keys: Option<&[CertificateOid]>) -> Result<CertificateProperties, CFError> {\n        unsafe {\n            let keys = keys.map(|oids| {\n                let oids = oids.iter().map(|oid| oid.to_str()).collect::<Vec<_>>();\n                CFArray::from_CFTypes(&oids)\n            });\n\n            let keys = match &keys {\n                Some(keys) => keys.as_concrete_TypeRef(),\n                None => ptr::null_mut(),\n            };\n\n            let mut error = ptr::null_mut();\n\n            let dictionary = SecCertificateCopyValues(self.as_concrete_TypeRef(), keys, &mut error);\n\n            if error.is_null() {\n                Ok(CertificateProperties(CFDictionary::wrap_under_create_rule(dictionary)))\n            } else {\n                Err(CFError::wrap_under_create_rule(error))\n            }\n        }\n    }\n\n    /// Returns the SHA-256 fingerprint of the certificate.\n    fn fingerprint(&self) -> Result<[u8; 32], CFError> {\n        let data = CFData::from_buffer(&self.to_der());\n        #[allow(deprecated)]\n        let hash = Builder::new()\n            .type_(DigestType::sha2())\n            .length(256)\n            .execute(&data)?;\n        Ok(hash.bytes().try_into().unwrap())\n    }\n}\n\n/// Properties associated with a certificate.\npub struct CertificateProperties(CFDictionary);\n\nimpl CertificateProperties {\n    /// Retrieves a specific property identified by its OID.\n    #[must_use]\n    pub fn get(&self, oid: CertificateOid) -> Option<CertificateProperty> {\n        unsafe {\n            self.0\n                .find(oid.as_ptr().to_void())\n                .map(|value| CertificateProperty(CFDictionary::wrap_under_get_rule(*value as *mut _)))\n        }\n    }\n}\n\n/// A property associated with a certificate.\npub struct CertificateProperty(CFDictionary);\n\nimpl CertificateProperty {\n    /// Returns the label of this property.\n    #[must_use]\n    pub fn label(&self) -> CFString {\n        unsafe {\n            CFString::wrap_under_get_rule((*self.0.get(kSecPropertyKeyLabel.to_void())).cast())\n        }\n    }\n\n    /// Returns an enum of the underlying data for this property.\n    #[must_use]\n    pub fn get(&self) -> PropertyType {\n        unsafe {\n            let type_ = CFString::wrap_under_get_rule(*self.0.get(kSecPropertyKeyType.to_void()) as *mut _);\n            let value = self.0.get(kSecPropertyKeyValue.to_void());\n\n            if type_ == CFString::wrap_under_get_rule(kSecPropertyTypeSection) {\n                PropertyType::Section(PropertySection(CFArray::wrap_under_get_rule((*value).cast())))\n            } else if type_ == CFString::wrap_under_get_rule(kSecPropertyTypeString) {\n                PropertyType::String(CFString::wrap_under_get_rule((*value).cast()))\n            } else {\n                PropertyType::__Unknown\n            }\n        }\n    }\n}\n\n/// A \"section\" property.\n///\n/// Sections are sequences of other properties.\npub struct PropertySection(CFArray<CFDictionary>);\n\nimpl PropertySection {\n    /// Returns an iterator over the properties in this section.\n    #[inline(always)]\n    #[must_use]\n    pub fn iter(&self) -> PropertySectionIter<'_> {\n        PropertySectionIter(self.0.iter())\n    }\n}\n\nimpl<'a> IntoIterator for &'a PropertySection {\n    type IntoIter = PropertySectionIter<'a>;\n    type Item = CertificateProperty;\n\n    #[inline(always)]\n    fn into_iter(self) -> PropertySectionIter<'a> {\n        self.iter()\n    }\n}\n\n/// An iterator over the properties in a section.\npub struct PropertySectionIter<'a>(CFArrayIterator<'a, CFDictionary>);\n\nimpl Iterator for PropertySectionIter<'_> {\n    type Item = CertificateProperty;\n\n    #[inline]\n    fn next(&mut self) -> Option<CertificateProperty> {\n        self.0.next().map(|t| CertificateProperty(t.clone()))\n    }\n\n    #[inline(always)]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        self.0.size_hint()\n    }\n}\n\n/// An enum of the various types of properties.\npub enum PropertyType {\n    /// A section.\n    Section(PropertySection),\n    /// A string.\n    String(CFString),\n    #[doc(hidden)]\n    __Unknown,\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use crate::test::certificate;\n    use std::collections::HashMap;\n\n    #[test]\n    fn common_name() {\n        let certificate = certificate();\n        assert_eq!(\"foobar.com\", p!(certificate.common_name()));\n    }\n\n    #[test]\n    fn public_key() {\n        let certificate = certificate();\n        p!(certificate.public_key());\n    }\n\n    #[test]\n    fn fingerprint() {\n        let certificate = certificate();\n        let fingerprint = p!(certificate.fingerprint());\n        assert_eq!(fingerprint.len(), 32);\n    }\n\n    #[test]\n    fn signature_algorithm() {\n        let certificate = certificate();\n        let properties = certificate\n            .properties(Some(&[CertificateOid::x509_v1_signature_algorithm()]))\n            .unwrap();\n        let value = properties\n            .get(CertificateOid::x509_v1_signature_algorithm())\n            .unwrap();\n        let PropertyType::Section(section) = value.get() else {\n            panic!()\n        };\n        let properties = section\n            .iter()\n            .map(|p| (p.label().to_string(), p.get()))\n            .collect::<HashMap<_, _>>();\n        let algorithm = match properties[\"Algorithm\"] {\n            PropertyType::String(ref s) => s.to_string(),\n            _ => panic!(),\n        };\n        // 1.2.840.113549.1.1.11 = sha256WithRSAEncryption\n        assert_eq!(algorithm, \"1.2.840.113549.1.1.11\");\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/certificate_oids.rs",
    "content": "//! OIDs associated with certificate properties.\nuse core_foundation::base::TCFType;\nuse core_foundation::string::CFString;\nuse core_foundation_sys::string::CFStringRef;\nuse security_framework_sys::certificate_oids::kSecOIDX509V1SignatureAlgorithm;\n\n/// An identifier of a property of a certificate.\n#[derive(Copy, Clone)]\npub struct CertificateOid(CFStringRef);\n\n#[allow(missing_docs)]\nimpl CertificateOid {\n    #[inline(always)]\n    #[must_use]\n    pub fn x509_v1_signature_algorithm() -> Self {\n        unsafe { Self(kSecOIDX509V1SignatureAlgorithm) }\n    }\n\n    /// Returns the underlying raw pointer corresponding to this OID.\n    #[inline(always)]\n    #[must_use]\n    // FIXME: Don't expose CFStringRef in Rust APIs\n    pub fn as_ptr(&self) -> CFStringRef {\n        self.0\n    }\n\n    /// Returns the string representation of the OID.\n    #[inline]\n    #[must_use]\n    // FIXME: Don't expose CFString in Rust APIs\n    pub fn to_str(&self) -> CFString {\n        unsafe { CFString::wrap_under_get_rule(self.0) }\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/code_signing.rs",
    "content": "//! Code signing services.\n\nuse core_foundation::base::{TCFType, TCFTypeRef, ToVoid};\nuse core_foundation::data::CFDataRef;\nuse core_foundation::dictionary::CFMutableDictionary;\nuse core_foundation::number::CFNumber;\nuse core_foundation::string::{CFString, CFStringRef};\nuse core_foundation::url::CFURL;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse libc::pid_t;\nuse security_framework_sys::code_signing::{\n    kSecCSBasicValidateOnly, kSecCSCheckAllArchitectures, kSecCSCheckGatekeeperArchitectures,\n    kSecCSCheckNestedCode, kSecCSCheckTrustedAnchors, kSecCSConsiderExpiration,\n    kSecCSDoNotValidateExecutable, kSecCSDoNotValidateResources, kSecCSEnforceRevocationChecks,\n    kSecCSFullReport, kSecCSNoNetworkAccess, kSecCSQuickCheck, kSecCSReportProgress,\n    kSecCSRestrictSidebandData, kSecCSRestrictSymlinks, kSecCSRestrictToAppLike,\n    kSecCSSingleThreaded, kSecCSStrictValidate, kSecCSUseSoftwareSigningCert, kSecCSValidatePEH,\n    kSecGuestAttributeAudit, kSecGuestAttributePid, SecCodeCheckValidity,\n    SecCodeCopyGuestWithAttributes, SecCodeCopyPath, SecCodeCopySelf, SecCodeGetTypeID, SecCodeRef,\n    SecRequirementCreateWithString, SecRequirementGetTypeID, SecRequirementRef,\n    SecStaticCodeCheckValidity, SecStaticCodeCreateWithPath, SecStaticCodeGetTypeID,\n    SecStaticCodeRef,\n};\nuse std::fmt::Debug;\nuse std::mem::MaybeUninit;\nuse std::str::FromStr;\n\nuse crate::{cvt, Result};\n\nbitflags::bitflags! {\n\n    /// Values that can be used in the flags parameter to most code signing\n    /// functions.\n    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n    pub struct Flags: u32 {\n        /// Use the default behaviour.\n        const NONE = 0;\n\n        /// For multi-architecture (universal) Mach-O programs, validate all\n        /// architectures included.\n        const CHECK_ALL_ARCHITECTURES = kSecCSCheckAllArchitectures;\n\n        /// Do not validate the contents of the main executable.\n        const DO_NOT_VALIDATE_EXECUTABLE = kSecCSDoNotValidateExecutable;\n\n        /// Do not validate the presence and contents of all bundle resources\n        /// if any.\n        const DO_NOT_VALIDATE_RESOURCES = kSecCSDoNotValidateResources;\n\n        /// Do not validate either the main executable or the bundle resources,\n        /// if any.\n        const BASIC_VALIDATE_ONLY = kSecCSBasicValidateOnly;\n\n        /// For code in bundle form, locate and recursively check embedded code.\n        const CHECK_NESTED_CODE = kSecCSCheckNestedCode;\n\n        /// Perform additional checks to ensure the validity of code in bundle\n        /// form.\n        const STRICT_VALIDATE = kSecCSStrictValidate;\n\n        /// Apple have not documented this flag.\n        const FULL_REPORT = kSecCSFullReport;\n\n        /// Apple have not documented this flag.\n        const CHECK_GATEKEEPER_ARCHITECTURES = kSecCSCheckGatekeeperArchitectures;\n\n        /// Apple have not documented this flag.\n        const RESTRICT_SYMLINKS = kSecCSRestrictSymlinks;\n\n        /// Apple have not documented this flag.\n        const RESTRICT_TO_APP_LIKE = kSecCSRestrictToAppLike;\n\n        /// Apple have not documented this flag.\n        const RESTRICT_SIDEBAND_DATA = kSecCSRestrictSidebandData;\n\n        /// Apple have not documented this flag.\n        const USE_SOFTWARE_SIGNING_CERT = kSecCSUseSoftwareSigningCert;\n\n        /// Apple have not documented this flag.\n        const VALIDATE_PEH = kSecCSValidatePEH;\n\n        /// Apple have not documented this flag.\n        const SINGLE_THREADED = kSecCSSingleThreaded;\n\n        /// Apple have not documented this flag.\n        const QUICK_CHECK = kSecCSQuickCheck;\n\n        /// Apple have not documented this flag.\n        const CHECK_TRUSTED_ANCHORS = kSecCSCheckTrustedAnchors;\n\n        /// Apple have not documented this flag.\n        const REPORT_PROGRESS = kSecCSReportProgress;\n\n        /// Apple have not documented this flag.\n        const NO_NETWORK_ACCESS = kSecCSNoNetworkAccess;\n\n        /// Apple have not documented this flag.\n        const ENFORCE_REVOCATION_CHECKS = kSecCSEnforceRevocationChecks;\n\n        /// Apple have not documented this flag.\n        const CONSIDER_EXPIRATION = kSecCSConsiderExpiration;\n    }\n}\n\nimpl Default for Flags {\n    #[inline(always)]\n    fn default() -> Self {\n        Self::NONE\n    }\n}\n\n/// A helper to create guest attributes, which are normally passed as a\n/// `CFDictionary` with varying types.\npub struct GuestAttributes {\n    inner: CFMutableDictionary,\n}\n\nimpl GuestAttributes {\n    // Not implemented:\n    // - architecture\n    // - canonical\n    // - dynamic code\n    // - dynamic code info plist\n    // - hash\n    // - mach port\n    // - sub-architecture\n\n    /// Creates a new, empty `GuestAttributes`. You must add values to it in\n    /// order for it to be of any use.\n    #[must_use]\n    pub fn new() -> Self {\n        Self {\n            inner: CFMutableDictionary::new(),\n        }\n    }\n\n    /// The guest's audit token.\n    pub fn set_audit_token(&mut self, token: CFDataRef) {\n        let key = unsafe { CFString::wrap_under_get_rule(kSecGuestAttributeAudit) };\n        self.inner.add(&key.as_CFTypeRef(), &token.to_void());\n    }\n\n    /// The guest's pid.\n    pub fn set_pid(&mut self, pid: pid_t) {\n        let key = unsafe { CFString::wrap_under_get_rule(kSecGuestAttributePid) };\n        let pid = CFNumber::from(pid);\n        self.inner.add(&key.as_CFTypeRef(), &pid.as_CFTypeRef());\n    }\n\n    /// Support for arbirtary guest attributes.\n    pub fn set_other<V: ToVoid<V>>(&mut self, key: CFStringRef, value: V) {\n        self.inner.add(&key.as_void_ptr(), &value.to_void());\n    }\n}\n\nimpl Default for GuestAttributes {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\ndeclare_TCFType! {\n    /// A code object representing signed code running on the system.\n    SecRequirement, SecRequirementRef\n}\nimpl_TCFType!(SecRequirement, SecRequirementRef, SecRequirementGetTypeID);\n\nimpl FromStr for SecRequirement {\n    type Err = crate::base::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        let text = CFString::new(s);\n        let mut requirement = MaybeUninit::uninit();\n\n        unsafe {\n            cvt(SecRequirementCreateWithString(\n                text.as_concrete_TypeRef(),\n                0,\n                requirement.as_mut_ptr(),\n            ))?;\n\n            Ok(Self::wrap_under_create_rule(requirement.assume_init()))\n        }\n    }\n}\n\ndeclare_TCFType! {\n    /// A code object representing signed code running on the system.\n    SecCode, SecCodeRef\n}\nimpl_TCFType!(SecCode, SecCodeRef, SecCodeGetTypeID);\n\nimpl Debug for SecCode {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_str(\"SecCode\")\n    }\n}\n\nimpl SecCode {\n    /// Retrieves the code object for the code making the call.\n    pub fn for_self(flags: Flags) -> Result<Self> {\n        let mut code = MaybeUninit::uninit();\n\n        unsafe {\n            cvt(SecCodeCopySelf(flags.bits(), code.as_mut_ptr()))?;\n            Ok(Self::wrap_under_create_rule(code.assume_init()))\n        }\n    }\n\n    /// Performs dynamic validation of signed code.\n    pub fn check_validity(&self, flags: Flags, requirement: &SecRequirement) -> Result<()> {\n        unsafe {\n            cvt(SecCodeCheckValidity(\n                self.as_concrete_TypeRef(),\n                flags.bits(),\n                requirement.as_concrete_TypeRef(),\n            ))\n        }\n    }\n\n    /// Asks a code host to identify one of its guests given\n    /// the type and value of specific attributes of the guest code.\n    ///\n    /// If `host` is `None` then the code signing root of trust (currently, the\n    // system kernel) should be used as the code host.\n    pub fn copy_guest_with_attribues(\n        host: Option<&Self>,\n        attrs: &GuestAttributes,\n        flags: Flags,\n    ) -> Result<Self> {\n        let mut code = MaybeUninit::uninit();\n\n        let host = match host {\n            Some(host) => host.as_concrete_TypeRef(),\n            None => std::ptr::null_mut(),\n        };\n\n        unsafe {\n            cvt(SecCodeCopyGuestWithAttributes(\n                host,\n                attrs.inner.as_concrete_TypeRef(),\n                flags.bits(),\n                code.as_mut_ptr(),\n            ))?;\n\n            Ok(Self::wrap_under_create_rule(code.assume_init()))\n        }\n    }\n\n    /// Retrieves the location on disk of signed code, given a code or static\n    /// code object.\n    // FIXME: Don't expose CFURL in Rust APIs.\n    pub fn path(&self, flags: Flags) -> Result<CFURL> {\n        let mut url = MaybeUninit::uninit();\n\n        // The docs say we can pass a SecCodeRef instead of a SecStaticCodeRef.\n        unsafe {\n            cvt(SecCodeCopyPath(\n                self.as_CFTypeRef() as _,\n                flags.bits(),\n                url.as_mut_ptr(),\n            ))?;\n\n            Ok(CFURL::wrap_under_create_rule(url.assume_init()))\n        }\n    }\n}\n\ndeclare_TCFType! {\n    /// A static code object representing signed code on disk.\n    SecStaticCode, SecStaticCodeRef\n}\nimpl_TCFType!(SecStaticCode, SecStaticCodeRef, SecStaticCodeGetTypeID);\n\nimpl SecStaticCode {\n    /// Creates a static code object representing the code at a specified file\n    /// system path.\n    pub fn from_path(path: &CFURL, flags: Flags) -> Result<Self> {\n        let mut code = MaybeUninit::uninit();\n\n        unsafe {\n            cvt(SecStaticCodeCreateWithPath(\n                path.as_concrete_TypeRef(),\n                flags.bits(),\n                code.as_mut_ptr(),\n            ))?;\n\n            Ok(Self::wrap_under_create_rule(code.assume_init()))\n        }\n    }\n\n    /// Retrieves the location on disk of signed code, given a code or static\n    /// code object.\n    // FIXME: Don't expose CFURL in Rust APIs.\n    pub fn path(&self, flags: Flags) -> Result<CFURL> {\n        let mut url = MaybeUninit::uninit();\n\n        // The docs say we can pass a SecCodeRef instead of a SecStaticCodeRef.\n        unsafe {\n            cvt(SecCodeCopyPath(\n                self.as_concrete_TypeRef(),\n                flags.bits(),\n                url.as_mut_ptr(),\n            ))?;\n\n            Ok(CFURL::wrap_under_create_rule(url.assume_init()))\n        }\n    }\n\n    /// Performs dynamic validation of signed code.\n    pub fn check_validity(&self, flags: Flags, requirement: &SecRequirement) -> Result<()> {\n        unsafe {\n            cvt(SecStaticCodeCheckValidity(\n                self.as_concrete_TypeRef(),\n                flags.bits(),\n                requirement.as_concrete_TypeRef(),\n            ))\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use core_foundation::data::CFData;\n    use libc::{c_uint, c_void, KERN_SUCCESS};\n\n    #[test]\n    fn path_to_static_code_and_back() {\n        let path = CFURL::from_path(\"/bin/bash\", false).unwrap();\n        let code = SecStaticCode::from_path(&path, Flags::NONE).unwrap();\n        assert_eq!(code.path(Flags::NONE).unwrap(), path);\n    }\n\n    #[test]\n    fn self_to_path() {\n        let path = CFURL::from_path(std::env::current_exe().unwrap(), false).unwrap();\n        let code = SecCode::for_self(Flags::NONE).unwrap();\n        assert_eq!(code.path(Flags::NONE).unwrap(), path);\n    }\n\n    #[test]\n    fn bash_is_signed_by_apple() {\n        let path = CFURL::from_path(\"/bin/bash\", false).unwrap();\n        let code = SecStaticCode::from_path(&path, Flags::NONE).unwrap();\n        let requirement: SecRequirement = \"anchor apple\".parse().unwrap();\n        code.check_validity(Flags::NONE, &requirement).unwrap();\n    }\n\n    #[cfg(target_arch = \"aarch64\")]\n    #[test]\n    fn self_is_not_signed_by_apple() {\n        let code = SecCode::for_self(Flags::NONE).unwrap();\n        let requirement: SecRequirement = \"anchor apple\".parse().unwrap();\n\n        assert_eq!(\n            code.check_validity(Flags::NONE, &requirement).unwrap_err().code(),\n            // \"code failed to satisfy specified code requirement(s)\"\n            -67050\n        );\n    }\n\n    #[cfg(not(target_arch = \"aarch64\"))]\n    #[test]\n    fn self_is_not_signed_by_apple() {\n        let code = SecCode::for_self(Flags::NONE).unwrap();\n        let requirement: SecRequirement = \"anchor apple\".parse().unwrap();\n\n        assert_eq!(\n            code.check_validity(Flags::NONE, &requirement).unwrap_err().code(),\n            // \"code object is not signed at all\"\n            -67062\n        );\n    }\n\n    #[test]\n    fn copy_kernel_guest_with_launchd_pid() {\n        let mut attrs = GuestAttributes::new();\n        attrs.set_pid(1);\n\n        assert_eq!(\n            SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE)\n                .unwrap()\n                .path(Flags::NONE)\n                .unwrap()\n                .get_string()\n                .to_string(),\n            \"file:///sbin/launchd\"\n        );\n    }\n\n    #[test]\n    fn copy_current_guest_with_launchd_pid() {\n        let host_code = SecCode::for_self(Flags::NONE).unwrap();\n\n        let mut attrs = GuestAttributes::new();\n        attrs.set_pid(1);\n\n        assert_eq!(\n            SecCode::copy_guest_with_attribues(Some(&host_code), &attrs, Flags::NONE)\n                .unwrap_err()\n                .code(),\n            // \"host has no guest with the requested attributes\"\n            -67065\n        );\n    }\n\n    #[test]\n    fn copy_kernel_guest_with_unmatched_pid() {\n        let mut attrs = GuestAttributes::new();\n        attrs.set_pid(999_999_999);\n\n        assert_eq!(\n            SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE)\n                .unwrap_err()\n                .code(),\n            // \"UNIX[No such process]\"\n            100003\n        );\n    }\n\n    #[test]\n    fn copy_kernel_guest_with_current_token() {\n        let mut token: [u8; 32] = [0; 32];\n        let mut token_len = 32u32;\n\n        enum OpaqueTaskName {}\n\n        unsafe extern \"C\" {\n            fn mach_task_self() -> *const OpaqueTaskName;\n            fn task_info(\n                task_name: *const OpaqueTaskName,\n                task_flavor: u32,\n                out: *mut c_void,\n                out_len: *mut u32,\n            ) -> i32;\n        }\n\n        const TASK_AUDIT_TOKEN: c_uint = 15;\n\n        let result = unsafe {\n            task_info(\n                mach_task_self(),\n                TASK_AUDIT_TOKEN,\n                token.as_mut_ptr().cast::<c_void>(),\n                &mut token_len,\n            )\n        };\n\n        assert_eq!(result, KERN_SUCCESS);\n\n        let token_data = CFData::from_buffer(&token);\n\n        let mut attrs = GuestAttributes::new();\n        attrs.set_audit_token(token_data.as_concrete_TypeRef());\n\n        assert_eq!(\n            SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE)\n                .unwrap()\n                .path(Flags::NONE)\n                .unwrap()\n                .to_path()\n                .unwrap(),\n            std::env::current_exe().unwrap()\n        );\n    }\n\n    #[test]\n    fn copy_kernel_guest_with_unmatched_token() {\n        let token: [u8; 32] = [0; 32];\n        let token_data = CFData::from_buffer(&token);\n\n        let mut attrs = GuestAttributes::new();\n        attrs.set_audit_token(token_data.as_concrete_TypeRef());\n\n        assert_eq!(\n            SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE).unwrap_err().code(),\n            // \"UNIX[No such process]\"\n            100003\n        );\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/digest_transform.rs",
    "content": "//! Digest Transform support\n\nuse core_foundation::base::{CFIndex, TCFType};\nuse core_foundation::data::CFData;\nuse core_foundation::error::CFError;\nuse core_foundation::string::CFString;\nuse core_foundation_sys::base::CFTypeRef;\nuse core_foundation_sys::data::CFDataRef;\nuse core_foundation_sys::string::CFStringRef;\nuse security_framework_sys::digest_transform::*;\nuse security_framework_sys::transform::kSecTransformInputAttributeName;\nuse std::ptr;\n#[allow(deprecated)]\nuse crate::os::macos::transform::SecTransform;\n\n#[derive(Debug, Copy, Clone)]\n/// A type of digest.\npub struct DigestType(CFStringRef);\n\n#[allow(missing_docs)]\nimpl DigestType {\n    #[inline(always)]\n    #[must_use]\n    pub fn hmac_md5() -> Self {\n        unsafe { Self(kSecDigestHMACMD5) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn hmac_sha1() -> Self {\n        unsafe { Self(kSecDigestHMACSHA1) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn hmac_sha2() -> Self {\n        unsafe { Self(kSecDigestHMACSHA2) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn md2() -> Self {\n        unsafe { Self(kSecDigestMD2) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn md4() -> Self {\n        unsafe { Self(kSecDigestMD4) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn md5() -> Self {\n        unsafe { Self(kSecDigestMD5) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn sha1() -> Self {\n        unsafe { Self(kSecDigestSHA1) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn sha2() -> Self {\n        unsafe { Self(kSecDigestSHA2) }\n    }\n\n    #[inline(always)]\n    fn to_type(self) -> CFTypeRef {\n        self.0 as CFTypeRef\n    }\n}\n\n/// A builder for digest transform operations.\n#[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\npub struct Builder {\n    digest_type: Option<DigestType>,\n    digest_length: Option<CFIndex>,\n    hmac_key: Option<CFData>,\n}\n\n#[allow(deprecated)]\nimpl Default for Builder {\n    #[inline(always)]\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\n#[allow(deprecated)]\nimpl Builder {\n    /// Returns a new builder with default settings.\n    #[inline(always)]\n    #[must_use]\n    pub fn new() -> Self {\n        Self {\n            digest_type: None,\n            digest_length: None,\n            hmac_key: None,\n        }\n    }\n\n    /// Sets the type of digest to perform.\n    ///\n    /// If not set, an appropriate digest will be selected for you.\n    #[inline]\n    pub fn type_(&mut self, digest_type: DigestType) -> &mut Self {\n        self.digest_type = Some(digest_type);\n        self\n    }\n\n    /// Sets the output length of the digest.\n    ///\n    /// If not set, an appropriate length will be selected for you. Some digest\n    /// types only support specific output lengths.\n    #[inline]\n    pub fn length(&mut self, digest_length: CFIndex) -> &mut Self {\n        self.digest_length = Some(digest_length);\n        self\n    }\n\n    /// Sets the key used for HMAC digests.\n    ///\n    /// Only applies to `HmacMd5`, `HmacSha1`, and `HmacSha2` digests.\n    #[inline]\n    pub fn hmac_key(&mut self, hmac_key: CFData) -> &mut Self {\n        self.hmac_key = Some(hmac_key);\n        self\n    }\n\n    /// Computes the digest of the data.\n    // FIXME: deprecate and remove: don't expose CFData in Rust APIs.\n    pub fn execute(&self, data: &CFData) -> Result<CFData, CFError> {\n        unsafe {\n            let digest_type = match &self.digest_type {\n                Some(digest_type) => digest_type.to_type(),\n                None => ptr::null(),\n            };\n\n            let digest_length = self.digest_length.unwrap_or(0);\n\n            let mut error = ptr::null_mut();\n            let transform = SecDigestTransformCreate(digest_type, digest_length, &mut error);\n            if transform.is_null() {\n                return Err(CFError::wrap_under_create_rule(error));\n            }\n            let mut transform = SecTransform::wrap_under_create_rule(transform);\n\n            if let Some(hmac_key) = &self.hmac_key {\n                let key = CFString::wrap_under_get_rule(kSecDigestHMACKeyAttribute);\n                transform.set_attribute(&key, hmac_key)?;\n            }\n\n            let key = CFString::wrap_under_get_rule(kSecTransformInputAttributeName);\n            transform.set_attribute(&key, data)?;\n\n            let result = transform.execute()?;\n            Ok(CFData::wrap_under_get_rule(result.as_CFTypeRef() as CFDataRef))\n        }\n    }\n}\n\n#[cfg(test)]\n#[allow(deprecated)]\nmod test {\n    #[allow(deprecated)]\n    use super::*;\n\n    #[test]\n    fn md5() {\n        let data = CFData::from_buffer(\"The quick brown fox jumps over the lazy dog\".as_bytes());\n        let hash = Builder::new().type_(DigestType::md5()).execute(&data).unwrap();\n        assert_eq!(hex::encode(hash.bytes()), \"9e107d9d372bb6826bd81d3542a419d6\");\n    }\n\n    #[test]\n    fn hmac_sha1() {\n        let data = CFData::from_buffer(\"The quick brown fox jumps over the lazy dog\".as_bytes());\n        let key = CFData::from_buffer(b\"key\");\n        let hash = Builder::new().type_(DigestType::hmac_sha1()).hmac_key(key).execute(&data).unwrap();\n        assert_eq!(hex::encode(hash.bytes()), \"de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9\");\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/encrypt_transform.rs",
    "content": "//! Encryption and Decryption transform support.\n\nuse core_foundation::base::TCFType;\nuse core_foundation::data::CFData;\nuse core_foundation::error::CFError;\nuse core_foundation::string::CFString;\nuse core_foundation_sys::data::CFDataRef;\nuse core_foundation_sys::string::CFStringRef;\nuse security_framework_sys::encrypt_transform::*;\nuse security_framework_sys::transform::kSecTransformInputAttributeName;\nuse std::ptr;\n\nuse crate::key::SecKey;\n#[allow(deprecated)]\nuse crate::os::macos::transform::SecTransform;\n\n#[derive(Debug, Copy, Clone)]\n/// The padding scheme to use for encryption.\npub struct Padding(CFStringRef);\n\nimpl Padding {\n    /// Do not pad.\n    #[inline(always)]\n    #[must_use]\n    pub fn none() -> Self {\n        unsafe { Self(kSecPaddingNoneKey) }\n    }\n\n    /// Use PKCS#1 padding.\n    #[inline(always)]\n    #[must_use]\n    pub fn pkcs1() -> Self {\n        unsafe { Self(kSecPaddingPKCS1Key) }\n    }\n\n    /// Use PKCS#5 padding.\n    #[inline(always)]\n    #[must_use]\n    pub fn pkcs5() -> Self {\n        unsafe { Self(kSecPaddingPKCS5Key) }\n    }\n\n    /// Use PKCS#7 padding.\n    #[inline(always)]\n    #[must_use]\n    pub fn pkcs7() -> Self {\n        unsafe { Self(kSecPaddingPKCS7Key) }\n    }\n\n    /// Use OAEP padding.\n    #[inline(always)]\n    #[must_use]\n    pub fn oaep() -> Self {\n        unsafe { Self(kSecPaddingOAEPKey) }\n    }\n\n    #[inline]\n    fn to_str(self) -> CFString {\n        unsafe { CFString::wrap_under_get_rule(self.0) }\n    }\n}\n\n/// The cipher mode to use.\n///\n/// Only applies to AES encryption.\n#[derive(Debug, Copy, Clone)]\npub struct Mode(CFStringRef);\n\n#[allow(missing_docs)]\nimpl Mode {\n    #[inline(always)]\n    #[must_use]\n    pub fn none() -> Self {\n        unsafe { Self(kSecModeNoneKey) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn ecb() -> Self {\n        unsafe { Self(kSecModeECBKey) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn cbc() -> Self {\n        unsafe { Self(kSecModeCBCKey) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn cfb() -> Self {\n        unsafe { Self(kSecModeCFBKey) }\n    }\n\n    #[inline(always)]\n    #[must_use]\n    pub fn ofb() -> Self {\n        unsafe { Self(kSecModeOFBKey) }\n    }\n\n    fn to_str(self) -> CFString {\n        unsafe { CFString::wrap_under_get_rule(self.0) }\n    }\n}\n\n/// A builder for encryption and decryption transform operations.\n#[derive(Default)]\n#[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\npub struct Builder {\n    padding: Option<Padding>,\n    mode: Option<Mode>,\n    iv: Option<CFData>,\n}\n\n#[allow(deprecated)]\nimpl Builder {\n    /// Creates a new `Builder` with a default configuration.\n    #[inline(always)]\n    #[must_use]\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    /// Selects the padding scheme to use.\n    ///\n    /// If not set, an appropriate scheme will be selected for you.\n    #[inline(always)]\n    pub fn padding(&mut self, padding: Padding) -> &mut Self {\n        self.padding = Some(padding);\n        self\n    }\n\n    /// Selects the encryption mode to use.\n    ///\n    /// If not set, an appropriate mode will be selected for you.\n    #[inline(always)]\n    pub fn mode(&mut self, mode: Mode) -> &mut Self {\n        self.mode = Some(mode);\n        self\n    }\n\n    /// Sets the initialization vector to use.\n    ///\n    /// If not set, an appropriate value will be supplied for you.\n    #[inline(always)]\n    pub fn iv(&mut self, iv: CFData) -> &mut Self {\n        self.iv = Some(iv);\n        self\n    }\n\n    /// Encrypts data with a provided key.\n    // FIXME: deprecate and remove: don't expose CFData in Rust APIs.\n    pub fn encrypt(&self, key: &SecKey, data: &CFData) -> Result<CFData, CFError> {\n        unsafe {\n            let mut error = ptr::null_mut();\n            let transform = SecEncryptTransformCreate(key.as_concrete_TypeRef(), &mut error);\n            if transform.is_null() {\n                return Err(CFError::wrap_under_create_rule(error));\n            }\n            let transform = SecTransform::wrap_under_create_rule(transform);\n\n            self.finish(transform, data)\n        }\n    }\n\n    /// Decrypts data with a provided key.\n    // FIXME: deprecate and remove: don't expose CFData in Rust APIs.\n    pub fn decrypt(&self, key: &SecKey, data: &CFData) -> Result<CFData, CFError> {\n        unsafe {\n            let mut error = ptr::null_mut();\n            let transform = SecDecryptTransformCreate(key.as_concrete_TypeRef(), &mut error);\n            if transform.is_null() {\n                return Err(CFError::wrap_under_create_rule(error));\n            }\n            let transform = SecTransform::wrap_under_create_rule(transform);\n\n            self.finish(transform, data)\n        }\n    }\n\n    fn finish(&self, mut transform: SecTransform, data: &CFData) -> Result<CFData, CFError> {\n        unsafe {\n            if let Some(padding) = &self.padding {\n                let key = CFString::wrap_under_get_rule(kSecPaddingKey);\n                transform.set_attribute(&key, &padding.to_str())?;\n            }\n\n            if let Some(mode) = &self.mode {\n                let key = CFString::wrap_under_get_rule(kSecEncryptionMode);\n                transform.set_attribute(&key, &mode.to_str())?;\n            }\n\n            if let Some(iv) = &self.iv {\n                let key = CFString::wrap_under_get_rule(kSecIVKey);\n                transform.set_attribute(&key, iv)?;\n            }\n\n            let key = CFString::wrap_under_get_rule(kSecTransformInputAttributeName);\n            transform.set_attribute(&key, data)?;\n\n            let result = transform.execute()?;\n            Ok(CFData::wrap_under_get_rule(result.as_CFTypeRef() as CFDataRef))\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use hex::FromHex;\n\n    #[allow(deprecated)]\n    use super::*;\n    use crate::os::macos::item::KeyType;\n    #[allow(deprecated)]\n    use crate::os::macos::key::SecKeyExt;\n\n    #[test]\n    #[allow(deprecated)]\n    fn cbc_mmt_256() {\n        // test 9\n        let key = \"87725bd43a45608814180773f0e7ab95a3c859d83a2130e884190e44d14c6996\";\n        let iv = \"e49651988ebbb72eb8bb80bb9abbca34\";\n        let ciphertext = \"5b97a9d423f4b97413f388d9a341e727bb339f8e18a3fac2f2fb85abdc8f135deb30054a\\\n                          1afdc9b6ed7da16c55eba6b0d4d10c74e1d9a7cf8edfaeaa684ac0bd9f9d24ba674955c7\\\n                          9dc6be32aee1c260b558ff07e3a4d49d24162011ff254db8be078e8ad07e648e6bf56793\\\n                          76cb4321a5ef01afe6ad8816fcc7634669c8c4389295c9241e45fff39f3225f7745032da\\\n                          eebe99d4b19bcb215d1bfdb36eda2c24\";\n        let plaintext = \"bfe5c6354b7a3ff3e192e05775b9b75807de12e38a626b8bf0e12d5fff78e4f1775aa7d79\\\n                         2d885162e66d88930f9c3b2cdf8654f56972504803190386270f0aa43645db187af41fcea\\\n                         639b1f8026ccdd0c23e0de37094a8b941ecb7602998a4b2604e69fc04219585d854600e0a\\\n                         d6f99a53b2504043c08b1c3e214d17cde053cbdf91daa999ed5b47c37983ba3ee254bc5c7\\\n                         93837daaa8c85cfc12f7f54f699f\";\n\n        let key = Vec::<u8>::from_hex(key).unwrap();\n        let key = CFData::from_buffer(&key);\n        #[allow(deprecated)]\n        let key = SecKey::from_data(KeyType::aes(), &key).unwrap();\n\n        let iv = Vec::<u8>::from_hex(iv).unwrap();\n\n        let ciphertext = Vec::<u8>::from_hex(ciphertext).unwrap();\n\n        let plaintext = Vec::<u8>::from_hex(plaintext).unwrap();\n\n        let decrypted = Builder::new()\n            .padding(Padding::none())\n            .iv(CFData::from_buffer(&iv))\n            .decrypt(&key, &CFData::from_buffer(&ciphertext))\n            .unwrap();\n\n        assert_eq!(plaintext, decrypted.bytes());\n\n        let encrypted = Builder::new()\n            .padding(Padding::none())\n            .iv(CFData::from_buffer(&iv))\n            .encrypt(&key, &CFData::from_buffer(&plaintext))\n            .unwrap();\n\n        assert_eq!(ciphertext, encrypted.bytes());\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/identity.rs",
    "content": "//! OSX specific extensions to identity functionality.\nuse core_foundation::array::CFArray;\nuse core_foundation::base::TCFType;\nuse security_framework_sys::identity::SecIdentityCreateWithCertificate;\nuse std::ptr;\n\nuse crate::base::Result;\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::identity::SecIdentity;\nuse crate::os::macos::keychain::SecKeychain;\n\n/// An extension trait adding OSX specific functionality to `SecIdentity`.\npub trait SecIdentityExt {\n    /// Creates an identity corresponding to a certificate, looking in the\n    /// provided keychains for the corresponding private key.\n    ///\n    /// To search the default keychains, use an empty slice for `keychains`.\n    ///\n    /// <https://developer.apple.com/documentation/security/1401160-secidentitycreatewithcertificate>\n    fn with_certificate(\n        keychains: &[SecKeychain],\n        certificate: &SecCertificate,\n    ) -> Result<SecIdentity>;\n}\n\nimpl SecIdentityExt for SecIdentity {\n    fn with_certificate(keychains: &[SecKeychain], certificate: &SecCertificate) -> Result<Self> {\n        let keychains = CFArray::from_CFTypes(keychains);\n        unsafe {\n            let mut identity = ptr::null_mut();\n            cvt(SecIdentityCreateWithCertificate(\n                if !keychains.is_empty() { keychains.as_CFTypeRef() } else { ptr::null() },\n                certificate.as_concrete_TypeRef(),\n                &mut identity,\n            ))?;\n            Ok(Self::wrap_under_create_rule(identity))\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use tempfile::tempdir;\n\n    use super::*;\n    use crate::os::macos::certificate::SecCertificateExt;\n    use crate::os::macos::import_export::ImportOptions;\n    use crate::os::macos::keychain::CreateOptions;\n    use crate::os::macos::test::identity;\n    use crate::test;\n\n    #[test]\n    fn certificate() {\n        let dir = p!(tempdir());\n        let identity = identity(dir.path());\n        let certificate = p!(identity.certificate());\n        assert_eq!(\"foobar.com\", p!(certificate.common_name()));\n    }\n\n    #[test]\n    fn private_key() {\n        let dir = p!(tempdir());\n        let identity = identity(dir.path());\n        p!(identity.private_key());\n    }\n\n    #[test]\n    fn with_certificate() {\n        let dir = p!(tempdir());\n\n        let keychain = p!(CreateOptions::new()\n            .password(\"foobar\")\n            .create(dir.path().join(\"test.keychain\")));\n\n        let key = include_bytes!(\"../../../test/server.key\");\n        p!(ImportOptions::new()\n            .filename(\"server.key\")\n            .keychain(&keychain)\n            .import(key));\n\n        let cert = test::certificate();\n        p!(SecIdentity::with_certificate(&[keychain], &cert));\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/import_export.rs",
    "content": "//! OSX specific extensions to import/export functionality.\n\nuse core_foundation::array::CFArray;\nuse core_foundation::base::{CFType, TCFType};\nuse core_foundation::data::CFData;\nuse core_foundation::string::CFString;\nuse security_framework_sys::base::errSecSuccess;\nuse security_framework_sys::import_export::*;\nuse std::ptr;\nuse std::str::FromStr;\n\nuse crate::base::{Error, Result};\nuse crate::certificate::SecCertificate;\nuse crate::identity::SecIdentity;\nuse crate::import_export::Pkcs12ImportOptions;\nuse crate::key::SecKey;\nuse crate::os::macos::access::SecAccess;\nuse crate::os::macos::keychain::SecKeychain;\n\n#[deprecated(note = \"Obsolete. Use Pkcs12ImportOptions directly.\")]\n/// Obsolete. Use Pkcs12ImportOptions directly.\npub trait Pkcs12ImportOptionsExt {\n    /// Specifies the keychain in which to import the identity.\n    ///\n    /// If this is not called, the default keychain will be used.\n    fn keychain(&mut self, keychain: SecKeychain) -> &mut Self;\n\n    /// Specifies the access control to be associated with the identity.\n    fn access(&mut self, access: SecAccess) -> &mut Self;\n}\n\n#[allow(deprecated)]\nimpl Pkcs12ImportOptionsExt for Pkcs12ImportOptions {\n    /// Moved to Pkcs12ImportOptions. Remove Pkcs12ImportOptionsExt trait.\n    fn keychain(&mut self, keychain: SecKeychain) -> &mut Self {\n        Self::keychain(self, keychain)\n    }\n\n    /// Moved to Pkcs12ImportOptions. Remove Pkcs12ImportOptionsExt trait.\n    fn access(&mut self, access: SecAccess) -> &mut Self {\n        Self::access(self, access)\n    }\n}\n\n/// A builder type to import Security Framework types from serialized formats.\n#[derive(Default)]\npub struct ImportOptions<'a> {\n    filename: Option<CFString>,\n    input_format: Option<SecExternalFormat>,\n    passphrase: Option<CFType>,\n    secure_passphrase: bool,\n    no_access_control: bool,\n    access: Option<SecAccess>,\n    alert_title: Option<CFString>,\n    alert_prompt: Option<CFString>,\n    items: Option<&'a mut SecItems>,\n    keychain: Option<SecKeychain>,\n}\n\nimpl<'a> ImportOptions<'a> {\n    /// Creates a new builder with default options.\n    #[inline(always)]\n    #[must_use]\n    pub fn new() -> Self {\n        ImportOptions::default()\n    }\n\n    /// Sets the filename from which the imported data came.\n    ///\n    /// The extension of the file will used as a hint for parsing.\n    #[inline]\n    pub fn filename(&mut self, filename: &str) -> &mut Self {\n        self.filename = Some(CFString::from_str(filename).unwrap());\n        self\n    }\n\n    /// Require input data to be PKCS#12\n    #[inline]\n    pub fn pkcs12(&mut self) -> &mut Self {\n        self.input_format = Some(kSecFormatPKCS12);\n        self\n    }\n\n    /// Sets the passphrase to be used to decrypt the imported data.\n    #[inline]\n    pub fn passphrase(&mut self, passphrase: &str) -> &mut Self {\n        self.passphrase = Some(CFString::from_str(passphrase).unwrap().into_CFType());\n        self\n    }\n\n    /// Sets the passphrase to be used to decrypt the imported data.\n    #[inline]\n    pub fn passphrase_bytes(&mut self, passphrase: &[u8]) -> &mut Self {\n        self.passphrase = Some(CFData::from_buffer(passphrase).into_CFType());\n        self\n    }\n\n    /// If set, the user will be prompted to imput the passphrase used to\n    /// decrypt the imported data.\n    #[inline(always)]\n    pub fn secure_passphrase(&mut self, secure_passphrase: bool) -> &mut Self {\n        self.secure_passphrase = secure_passphrase;\n        self\n    }\n\n    /// If set, imported items will have no access controls imposed on them.\n    #[inline(always)]\n    pub fn no_access_control(&mut self, no_access_control: bool) -> &mut Self {\n        self.no_access_control = no_access_control;\n        self\n    }\n\n    /// Specifies the access control to be associated with the identity. macOS only.\n    #[inline(always)]\n    pub fn access(&mut self, access: SecAccess) -> &mut Self {\n        self.access = Some(access);\n        self\n    }\n\n    /// Sets the title of the alert popup used with the `secure_passphrase`\n    /// option.\n    #[inline]\n    pub fn alert_title(&mut self, alert_title: &str) -> &mut Self {\n        self.alert_title = Some(CFString::from_str(alert_title).unwrap());\n        self\n    }\n\n    /// Sets the prompt of the alert popup used with the `secure_passphrase`\n    /// option.\n    #[inline]\n    pub fn alert_prompt(&mut self, alert_prompt: &str) -> &mut Self {\n        self.alert_prompt = Some(CFString::from_str(alert_prompt).unwrap());\n        self\n    }\n\n    /// Sets the object into which imported items will be placed.\n    #[inline(always)]\n    pub fn items(&mut self, items: &'a mut SecItems) -> &mut Self {\n        self.items = Some(items);\n        self\n    }\n\n    /// Sets the keychain into which items will be imported.\n    ///\n    /// This must be specified to import `SecIdentity`s.\n    #[inline]\n    pub fn keychain(&mut self, keychain: &SecKeychain) -> &mut Self {\n        self.keychain = Some(keychain.clone());\n        self\n    }\n\n    /// Imports items from serialized data.\n    pub fn import(&mut self, data: &[u8]) -> Result<()> {\n        let data = CFData::from_buffer(data);\n        let data = data.as_concrete_TypeRef();\n\n        let filename = match &self.filename {\n            Some(filename) => filename.as_concrete_TypeRef(),\n            None => ptr::null(),\n        };\n\n        let mut input_format_out;\n        let input_format_ptr = match self.input_format {\n            None => ptr::null_mut(),\n            Some(format) => {\n                input_format_out = format;\n                &mut input_format_out\n            },\n        };\n\n        let mut key_params = SecItemImportExportKeyParameters {\n            version: SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION,\n            flags: 0,\n            passphrase: ptr::null(),\n            alertTitle: ptr::null(),\n            alertPrompt: ptr::null(),\n            accessRef: ptr::null_mut(),\n            keyUsage: ptr::null_mut(),\n            keyAttributes: ptr::null(),\n        };\n\n        if let Some(passphrase) = &self.passphrase {\n            key_params.passphrase = passphrase.as_CFTypeRef();\n        }\n\n        if self.secure_passphrase {\n            key_params.flags |= kSecKeySecurePassphrase;\n        }\n\n        if self.no_access_control {\n            key_params.flags |= kSecKeyNoAccessControl;\n        }\n\n        if let Some(access) = &self.access {\n            key_params.accessRef = access.as_concrete_TypeRef();\n        }\n\n        if let Some(alert_title) = &self.alert_title {\n            key_params.alertTitle = alert_title.as_concrete_TypeRef();\n        }\n\n        if let Some(alert_prompt) = &self.alert_prompt {\n            key_params.alertPrompt = alert_prompt.as_concrete_TypeRef();\n        }\n\n        let keychain = match &self.keychain {\n            Some(keychain) => keychain.as_concrete_TypeRef(),\n            None => ptr::null_mut(),\n        };\n\n        let mut raw_items = ptr::null();\n        let items_ref = match self.items {\n            Some(_) => &mut raw_items,\n            None => ptr::null_mut(),\n        };\n\n        unsafe {\n            let ret = SecItemImport(\n                data,\n                filename,\n                input_format_ptr,\n                ptr::null_mut(),\n                0,\n                &key_params,\n                keychain,\n                items_ref,\n            );\n            if ret != errSecSuccess {\n                return Err(Error::from_code(ret));\n            }\n\n            if let Some(items) = &mut self.items {\n                let raw_items = CFArray::<CFType>::wrap_under_create_rule(raw_items);\n                for item in raw_items.iter() {\n                    let type_id = item.type_of();\n                    if type_id == SecCertificate::type_id() {\n                        items.certificates.push(SecCertificate::wrap_under_get_rule(item.as_CFTypeRef() as *mut _));\n                    } else if type_id == SecIdentity::type_id() {\n                        items.identities.push(SecIdentity::wrap_under_get_rule(item.as_CFTypeRef() as *mut _));\n                    } else if type_id == SecKey::type_id() {\n                        items.keys.push(SecKey::wrap_under_get_rule(item.as_CFTypeRef() as *mut _));\n                    } else {\n                        panic!(\"Got bad type from SecItemImport: {type_id}\");\n                    }\n                }\n            }\n        }\n\n        Ok(())\n    }\n}\n\n/// A type which holds items imported from serialized data.\n///\n/// Pass a reference to `ImportOptions::items`.\n#[derive(Default)]\npub struct SecItems {\n    /// Imported certificates.\n    pub certificates: Vec<SecCertificate>,\n    /// Imported identities.\n    pub identities: Vec<SecIdentity>,\n    /// Imported keys.\n    pub keys: Vec<SecKey>,\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use crate::import_export::*;\n    use crate::os::macos::keychain;\n    use tempfile::tempdir;\n\n    #[test]\n    fn certificate() {\n        let data = include_bytes!(\"../../../test/server.der\");\n        let mut items = SecItems::default();\n        ImportOptions::new()\n            .filename(\"server.der\")\n            .items(&mut items)\n            .import(data)\n            .unwrap();\n        assert_eq!(1, items.certificates.len());\n        assert_eq!(0, items.identities.len());\n        assert_eq!(0, items.keys.len());\n    }\n\n    #[test]\n    fn key() {\n        let data = include_bytes!(\"../../../test/server.key\");\n        let mut items = SecItems::default();\n        ImportOptions::new()\n            .filename(\"server.key\")\n            .items(&mut items)\n            .import(data)\n            .unwrap();\n        assert_eq!(0, items.certificates.len());\n        assert_eq!(0, items.identities.len());\n        assert_eq!(1, items.keys.len());\n    }\n\n    #[test]\n    fn identity() {\n        let dir = tempdir().unwrap();\n        let keychain = keychain::CreateOptions::new()\n            .password(\"password\")\n            .create(dir.path().join(\"identity.keychain\"))\n            .unwrap();\n\n        let data = include_bytes!(\"../../../test/server.p12\");\n        let identities = Pkcs12ImportOptions::new()\n            .passphrase(\"password123\")\n            .keychain(keychain)\n            .import(data)\n            .unwrap();\n        assert_eq!(1, identities.len());\n    }\n\n    #[test]\n    #[ignore] // since it requires manual intervention\n    fn secure_passphrase_identity() {\n        let dir = tempdir().unwrap();\n        let keychain = keychain::CreateOptions::new()\n            .password(\"password\")\n            .create(dir.path().join(\"identity.keychain\"))\n            .unwrap();\n\n        let data = include_bytes!(\"../../../test/server.p12\");\n        let mut items = SecItems::default();\n        ImportOptions::new()\n            .filename(\"server.p12\")\n            .secure_passphrase(true)\n            .alert_title(\"alert title\")\n            .alert_prompt(\"alert prompt\")\n            .items(&mut items)\n            .keychain(&keychain)\n            .import(data)\n            .unwrap();\n        assert_eq!(1, items.identities.len());\n        assert_eq!(0, items.certificates.len());\n        assert_eq!(0, items.keys.len());\n    }\n\n    #[test]\n    fn pkcs12_import() {\n        let dir = tempdir().unwrap();\n        let keychain = keychain::CreateOptions::new()\n            .password(\"password\")\n            .create(dir.path().join(\"pkcs12_import\"))\n            .unwrap();\n\n        let data = include_bytes!(\"../../../test/server.p12\");\n        let identities = p!(Pkcs12ImportOptions::new()\n            .passphrase(\"password123\")\n            .keychain(keychain)\n            .import(data));\n        assert_eq!(1, identities.len());\n        assert!(identities[0].key_id.is_some());\n        assert_eq!(identities[0].key_id.as_ref().unwrap().len(), 20);\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/item.rs",
    "content": "//! OSX specific functionality for items.\nuse crate::item::ItemSearchOptions;\nuse crate::os::macos::keychain::SecKeychain;\n\n// Moved to crate::Key\npub use crate::key::KeyType;\n\n// TODO: mark as deprecated\n#[doc(hidden)]\n/// An obsolete trait for `ItemSearchOptions`. Use methods on `ItemSearchOptions` directly.\npub trait ItemSearchOptionsExt {\n    /// Search within the specified keychains.\n    ///\n    /// If this is not called, the default keychain will be searched.\n    fn keychains(&mut self, keychains: &[SecKeychain]) -> &mut Self;\n\n    // Do not extend this trait; use `impl ItemSearchOptions` directly\n}\n\nimpl ItemSearchOptionsExt for ItemSearchOptions {\n    fn keychains(&mut self, keychains: &[SecKeychain]) -> &mut Self {\n        Self::keychains(self, keychains)\n    }\n\n    // Do not extend this trait; use `impl ItemSearchOptions` directly\n}\n\n#[cfg(test)]\nmod test {\n    use crate::item::*;\n    use crate::os::macos::certificate::SecCertificateExt;\n    use crate::os::macos::test::keychain;\n    use tempfile::tempdir;\n\n    #[test]\n    fn find_certificate() {\n        let dir = p!(tempdir());\n        let keychain = keychain(dir.path());\n        let results = p!(ItemSearchOptions::new()\n            .keychains(&[keychain])\n            .class(ItemClass::certificate())\n            .search());\n        assert_eq!(1, results.len());\n        let SearchResult::Ref(Reference::Certificate(certificate)) = &results[0] else {\n            panic!(\"expected certificate\")\n        };\n        assert_eq!(\"foobar.com\", p!(certificate.common_name()));\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/key.rs",
    "content": "//! OSX specific functionality for keys.\nuse core_foundation::base::TCFType;\nuse core_foundation::data::CFData;\nuse core_foundation::dictionary::CFDictionary;\nuse core_foundation::error::CFError;\nuse core_foundation::string::CFString;\nuse security_framework_sys::item::kSecAttrKeyType;\nuse std::ptr;\n\nuse crate::key::{KeyType, SecKey};\n\n/// An extension trait adding OSX specific functionality to `SecKey`.\n#[deprecated(note = \"Deprecated by Apple. There's no replacement for symmetric keys\")]\npub trait SecKeyExt {\n    /// Creates a new `SecKey` from a buffer containing key data.\n    fn from_data(key_type: KeyType, key_data: &CFData) -> Result<SecKey, CFError>;\n}\n\n#[allow(deprecated)]\nimpl SecKeyExt for SecKey {\n    fn from_data(key_type: KeyType, key_data: &CFData) -> Result<Self, CFError> {\n        unsafe {\n            let key = CFString::wrap_under_get_rule(kSecAttrKeyType);\n            let type_ = CFString::wrap_under_get_rule(key_type.as_cfstring());\n            let dict = CFDictionary::from_CFType_pairs(&[(key, type_)]);\n\n            let mut err = ptr::null_mut();\n            let key = security_framework_sys::key::SecKeyCreateFromData(\n                dict.as_concrete_TypeRef(),\n                key_data.as_concrete_TypeRef(),\n                &mut err,\n            );\n            if key.is_null() {\n                Err(CFError::wrap_under_create_rule(err))\n            } else {\n                Ok(Self::wrap_under_create_rule(key))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/keychain.rs",
    "content": "//! Keychain support.\n//!\n//! Apple has deprecated `SecKeychain`.\n\nuse core_foundation::base::{Boolean, TCFType};\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse security_framework_sys::base::{errSecSuccess, SecKeychainRef};\nuse security_framework_sys::keychain::*;\nuse std::ffi::CString;\nuse std::os::raw::c_void;\nuse std::os::unix::ffi::OsStrExt;\nuse std::path::Path;\nuse std::ptr;\n\nuse crate::base::{Error, Result};\nuse crate::cvt;\nuse crate::os::macos::access::SecAccess;\n\npub use security_framework_sys::keychain::SecPreferencesDomain;\n\ndeclare_TCFType! {\n    /// A type representing a keychain.\n    SecKeychain, SecKeychainRef\n}\nimpl_TCFType!(SecKeychain, SecKeychainRef, SecKeychainGetTypeID);\n\nunsafe impl Sync for SecKeychain {}\nunsafe impl Send for SecKeychain {}\n\nimpl SecKeychain {\n    /// Creates a `SecKeychain` object corresponding to the user's default\n    /// keychain.\n    #[inline]\n    #[allow(clippy::should_implement_trait)]\n    pub fn default() -> Result<Self> {\n        unsafe {\n            let mut keychain = ptr::null_mut();\n            cvt(SecKeychainCopyDefault(&mut keychain))?;\n            Ok(Self::wrap_under_create_rule(keychain))\n        }\n    }\n\n    /// Creates a `SecKeychain` object corresponding to the user's default\n    /// keychain for the given domain.\n    pub fn default_for_domain(domain: SecPreferencesDomain) -> Result<Self> {\n        unsafe {\n            let mut keychain = ptr::null_mut();\n            cvt(SecKeychainCopyDomainDefault(domain, &mut keychain))?;\n            Ok(Self::wrap_under_create_rule(keychain))\n        }\n    }\n\n    /// Opens a keychain from a file.\n    #[allow(deprecated)]\n    pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {\n        let path_name = [\n            path.as_ref().as_os_str().as_bytes(),\n            std::slice::from_ref(&0),\n        ]\n        .concat();\n\n        unsafe {\n            let mut keychain = ptr::null_mut();\n            cvt(SecKeychainOpen(path_name.as_ptr().cast(), &mut keychain))?;\n            Ok(Self::wrap_under_create_rule(keychain))\n        }\n    }\n\n    /// Unlocks the keychain.\n    ///\n    /// If a password is not specified, the user will be prompted to enter it.\n    #[allow(deprecated)]\n    pub fn unlock(&mut self, password: Option<&str>) -> Result<()> {\n        let (len, ptr, use_password) = match password {\n            Some(password) => (password.len(), password.as_ptr().cast(), true),\n            None => (0, ptr::null(), false),\n        };\n\n        unsafe {\n            cvt(SecKeychainUnlock(\n                self.as_concrete_TypeRef(),\n                len as u32,\n                ptr,\n                Boolean::from(use_password),\n            ))\n        }\n    }\n\n    /// Sets settings of the keychain.\n    #[inline]\n    pub fn set_settings(&mut self, settings: &KeychainSettings) -> Result<()> {\n        unsafe {\n            cvt(SecKeychainSetSettings(\n                self.as_concrete_TypeRef(),\n                &settings.0,\n            ))\n        }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    /// Disables the user interface for keychain services functions that\n    /// automatically display a user interface.\n    pub fn disable_user_interaction() -> Result<KeychainUserInteractionLock> {\n        let code = unsafe { SecKeychainSetUserInteractionAllowed(0u8) };\n\n        if code == errSecSuccess {\n            Ok(KeychainUserInteractionLock)\n        } else {\n            Err(Error::from_code(code))\n        }\n    }\n\n    #[cfg(target_os = \"macos\")]\n    /// Indicates whether keychain services functions that normally display a\n    /// user interaction are allowed to do so.\n    pub fn user_interaction_allowed() -> Result<bool> {\n        let mut state: Boolean = 0;\n        let code = unsafe { SecKeychainGetUserInteractionAllowed(&mut state) };\n\n        if code == errSecSuccess {\n            Ok(state != 0)\n        } else {\n            Err(Error::from_code(code))\n        }\n    }\n}\n\n/// A builder type to create new keychains.\n#[derive(Default)]\npub struct CreateOptions {\n    password: Option<String>,\n    prompt_user: bool,\n    access: Option<SecAccess>,\n}\n\nimpl CreateOptions {\n    /// Creates a new builder with default options.\n    #[inline(always)]\n    #[must_use]\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    /// Sets the password to be used to protect the keychain.\n    #[inline]\n    pub fn password(&mut self, password: &str) -> &mut Self {\n        self.password = Some(password.into());\n        self\n    }\n\n    /// If set, the user will be prompted to provide a password used to\n    /// protect the keychain.\n    #[inline(always)]\n    pub fn prompt_user(&mut self, prompt_user: bool) -> &mut Self {\n        self.prompt_user = prompt_user;\n        self\n    }\n\n    /// Sets the access control applied to the keychain.\n    #[inline(always)]\n    pub fn access(&mut self, access: SecAccess) -> &mut Self {\n        self.access = Some(access);\n        self\n    }\n\n    /// Creates a new keychain at the specified location on the filesystem.\n    #[allow(deprecated)]\n    pub fn create<P: AsRef<Path>>(&self, path: P) -> Result<SecKeychain> {\n        unsafe {\n            let path_name = path.as_ref().as_os_str().as_bytes();\n            // FIXME\n            let path_name = CString::new(path_name).unwrap();\n\n            let (password, password_len) = match &self.password {\n                Some(password) => (password.as_ptr().cast::<c_void>(), password.len() as u32),\n                None => (ptr::null(), 0),\n            };\n\n            let access = match &self.access {\n                Some(access) => access.as_concrete_TypeRef(),\n                None => ptr::null_mut(),\n            };\n\n            let mut keychain = ptr::null_mut();\n            cvt(SecKeychainCreate(\n                path_name.as_ptr(),\n                password_len,\n                password,\n                Boolean::from(self.prompt_user),\n                access,\n                &mut keychain,\n            ))?;\n\n            Ok(SecKeychain::wrap_under_create_rule(keychain))\n        }\n    }\n}\n\n/// Settings associated with a `SecKeychain`.\npub struct KeychainSettings(SecKeychainSettings);\n\nimpl KeychainSettings {\n    /// Creates a new `KeychainSettings` with default settings.\n    #[inline]\n    #[must_use]\n    pub fn new() -> Self {\n        Self(SecKeychainSettings {\n            version: SEC_KEYCHAIN_SETTINGS_VERS1,\n            lockOnSleep: 0,\n            useLockInterval: 0,\n            lockInterval: i32::MAX as u32,\n        })\n    }\n\n    /// If set, the keychain will automatically lock when the computer sleeps.\n    ///\n    /// Defaults to `false`.\n    #[inline(always)]\n    pub fn set_lock_on_sleep(&mut self, lock_on_sleep: bool) {\n        self.0.lockOnSleep = Boolean::from(lock_on_sleep);\n    }\n\n    /// Sets the interval of time in seconds after which the keychain is\n    /// automatically locked.\n    ///\n    /// Defaults to `None`.\n    pub fn set_lock_interval(&mut self, lock_interval: Option<u32>) {\n        if let Some(lock_interval) = lock_interval {\n            self.0.useLockInterval = 1;\n            self.0.lockInterval = lock_interval;\n        } else {\n            self.0.useLockInterval = 0;\n            self.0.lockInterval = i32::MAX as u32;\n        }\n    }\n}\n\nimpl Default for KeychainSettings {\n    #[inline(always)]\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\n#[cfg(target_os = \"macos\")]\n#[must_use = \"The user interaction is disabled for the lifetime of the returned object\"]\n/// Automatically re-enables user interaction.\npub struct KeychainUserInteractionLock;\n\n#[cfg(target_os = \"macos\")]\nimpl Drop for KeychainUserInteractionLock {\n    #[inline(always)]\n    fn drop(&mut self) {\n        unsafe { SecKeychainSetUserInteractionAllowed(1u8) };\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use tempfile::tempdir;\n\n    use super::*;\n\n    #[test]\n    fn create_options() {\n        let dir = tempdir().unwrap();\n\n        let mut keychain = CreateOptions::new()\n            .password(\"foobar\")\n            .create(dir.path().join(\"test.keychain\"))\n            .unwrap();\n\n        keychain.set_settings(&KeychainSettings::new()).unwrap();\n    }\n\n    #[test]\n    fn disable_user_interaction() {\n        assert!(SecKeychain::user_interaction_allowed().unwrap());\n        {\n            let _lock = SecKeychain::disable_user_interaction().unwrap();\n            assert!(!SecKeychain::user_interaction_allowed().unwrap());\n        }\n        assert!(SecKeychain::user_interaction_allowed().unwrap());\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/keychain_item.rs",
    "content": "#![allow(deprecated)]\n//! Keychain item support.\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse security_framework_sys::base::SecKeychainItemRef;\nuse security_framework_sys::keychain_item::SecKeychainItemGetTypeID;\nuse std::fmt;\n\ndeclare_TCFType! {\n    /// A type representing a keychain item.\n    SecKeychainItem, SecKeychainItemRef\n}\nimpl_TCFType!(\n    SecKeychainItem,\n    SecKeychainItemRef,\n    SecKeychainItemGetTypeID\n);\n\nunsafe impl Sync for SecKeychainItem {}\nunsafe impl Send for SecKeychainItem {}\n\nimpl fmt::Debug for SecKeychainItem {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"SecKeychainItem\").finish_non_exhaustive()\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/mod.rs",
    "content": "//! OSX specific extensions.\n\npub mod access;\npub mod certificate;\npub mod certificate_oids;\npub mod code_signing;\npub mod digest_transform;\npub mod encrypt_transform;\npub mod identity;\npub mod import_export;\npub mod item;\npub mod key;\npub mod keychain;\npub mod keychain_item;\npub mod passwords;\npub mod secure_transport;\npub mod transform;\n\n#[cfg(test)]\npub(crate) mod test {\n    use crate::identity::SecIdentity;\n    use crate::item::{ItemClass, ItemSearchOptions, Reference, SearchResult};\n    use crate::os::macos::keychain::SecKeychain;\n    use std::fs::File;\n    use std::io::prelude::*;\n    use std::path::Path;\n\n    #[must_use]\n    pub(crate) fn identity(dir: &Path) -> SecIdentity {\n        // FIXME https://github.com/rust-lang/rust/issues/30018\n        let keychain = keychain(dir);\n        let mut items = p!(ItemSearchOptions::new()\n            .class(ItemClass::identity())\n            .keychains(&[keychain])\n            .search());\n        match items.pop().unwrap() {\n            SearchResult::Ref(Reference::Identity(identity)) => identity,\n            _ => panic!(\"expected identity\"),\n        }\n    }\n\n    #[must_use]\n    pub(crate) fn keychain(dir: &Path) -> SecKeychain {\n        let path = dir.join(\"server.keychain\");\n        let mut file = p!(File::create(&path));\n        p!(file.write_all(include_bytes!(\"../../../test/server.keychain\")));\n        drop(file);\n\n        let mut keychain = p!(SecKeychain::open(&path));\n        p!(keychain.unlock(Some(\"password123\")));\n        keychain\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/passwords.rs",
    "content": "//! Password support.\n\nuse crate::os::macos::keychain::SecKeychain;\nuse crate::os::macos::keychain_item::SecKeychainItem;\nuse core_foundation::array::CFArray;\nuse core_foundation::base::TCFType;\npub use security_framework_sys::keychain::{SecAuthenticationType, SecProtocolType};\nuse security_framework_sys::keychain::{\n    SecKeychainAddGenericPassword, SecKeychainAddInternetPassword, SecKeychainFindGenericPassword,\n    SecKeychainFindInternetPassword,\n};\n#[allow(deprecated)]\nuse security_framework_sys::keychain_item::{\n    SecKeychainItemDelete, SecKeychainItemFreeContent, SecKeychainItemModifyAttributesAndData,\n};\nuse std::fmt;\nuse std::fmt::Write;\nuse std::ops::Deref;\nuse std::ptr;\nuse std::slice;\n\nuse crate::base::Result;\nuse crate::cvt;\n\n/// Password slice. Use `.as_ref()` to get `&[u8]` or `.to_owned()` to get `Vec<u8>`\npub struct SecKeychainItemPassword {\n    data: *const u8,\n    data_len: usize,\n}\n\nimpl fmt::Debug for SecKeychainItemPassword {\n    #[cold]\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        for _ in 0..self.data_len {\n            f.write_char('•')?;\n        }\n        Ok(())\n    }\n}\n\nimpl AsRef<[u8]> for SecKeychainItemPassword {\n    #[inline]\n    fn as_ref(&self) -> &[u8] {\n        unsafe { slice::from_raw_parts(self.data, self.data_len) }\n    }\n}\n\nimpl Deref for SecKeychainItemPassword {\n    type Target = [u8];\n\n    #[inline(always)]\n    fn deref(&self) -> &Self::Target {\n        self.as_ref()\n    }\n}\n\nimpl Drop for SecKeychainItemPassword {\n    #[inline]\n    fn drop(&mut self) {\n        #[allow(deprecated)]\n        unsafe {\n            SecKeychainItemFreeContent(ptr::null_mut(), self.data as *mut _);\n        }\n    }\n}\n\nimpl SecKeychainItem {\n    /// Modify keychain item in-place, replacing its password with the given one\n    pub fn set_password(&mut self, password: &[u8]) -> Result<()> {\n        #[allow(deprecated)]\n        unsafe {\n            cvt(SecKeychainItemModifyAttributesAndData(\n                self.as_concrete_TypeRef(),\n                ptr::null(),\n                password.len() as u32,\n                password.as_ptr().cast(),\n            ))?;\n        }\n        Ok(())\n    }\n\n    /// Delete this item from its keychain\n    #[inline]\n    pub fn delete(self) {\n        #[allow(deprecated)]\n        unsafe {\n            SecKeychainItemDelete(self.as_concrete_TypeRef());\n        }\n    }\n}\n\n/// Find a generic password.\n///\n/// The underlying system supports passwords with 0 values, so this\n/// returns a vector of bytes rather than a string.\n///\n/// * `keychains` is an array of keychains to search or None to search the default keychain.\n/// * `service` is the name of the service to search for.\n/// * `account` is the name of the account to search for.\npub fn find_generic_password(\n    keychains: Option<&[SecKeychain]>,\n    service: &str,\n    account: &str,\n) -> Result<(SecKeychainItemPassword, SecKeychainItem)> {\n    let keychains_or_none = keychains.map(CFArray::from_CFTypes);\n\n    let keychains_or_null = match &keychains_or_none {\n        None => ptr::null(),\n        Some(keychains) => keychains.as_CFTypeRef(),\n    };\n\n    let mut data_len = 0;\n    let mut data = ptr::null_mut();\n    let mut item = ptr::null_mut();\n\n    unsafe {\n        cvt(SecKeychainFindGenericPassword(\n            keychains_or_null,\n            service.len() as u32,\n            service.as_ptr().cast(),\n            account.len() as u32,\n            account.as_ptr().cast(),\n            &mut data_len,\n            &mut data,\n            &mut item,\n        ))?;\n        Ok((\n            SecKeychainItemPassword {\n                data: data as *const _,\n                data_len: data_len as usize,\n            },\n            SecKeychainItem::wrap_under_create_rule(item),\n        ))\n    }\n}\n\n/// * `keychains` is an array of keychains to search or None to search the default keychain.\n/// * `server`: server name.\n/// * `security_domain`: security domain. This parameter is optional.\n/// * `account`: account name.\n/// * `path`: the path.\n/// * `port`: The TCP/IP port number.\n/// * `protocol`: The protocol associated with this password.\n/// * `authentication_type`: The authentication scheme used.\n#[allow(clippy::too_many_arguments)]\npub fn find_internet_password(\n    keychains: Option<&[SecKeychain]>,\n    server: &str,\n    security_domain: Option<&str>,\n    account: &str,\n    path: &str,\n    port: Option<u16>,\n    protocol: SecProtocolType,\n    authentication_type: SecAuthenticationType,\n) -> Result<(SecKeychainItemPassword, SecKeychainItem)> {\n    let keychains_or_none = keychains.map(CFArray::from_CFTypes);\n\n    let keychains_or_null = match &keychains_or_none {\n        None => ptr::null(),\n        Some(keychains) => keychains.as_CFTypeRef(),\n    };\n\n    let mut data_len = 0;\n    let mut data = ptr::null_mut();\n    let mut item = ptr::null_mut();\n\n    unsafe {\n        cvt(SecKeychainFindInternetPassword(\n            keychains_or_null,\n            server.len() as u32,\n            server.as_ptr().cast(),\n            security_domain.map_or(0, |s| s.len() as u32),\n            security_domain.map_or(ptr::null(), |s| s.as_ptr().cast()),\n            account.len() as u32,\n            account.as_ptr().cast(),\n            path.len() as u32,\n            path.as_ptr().cast(),\n            port.unwrap_or(0),\n            protocol,\n            authentication_type,\n            &mut data_len,\n            &mut data,\n            &mut item,\n        ))?;\n        Ok((\n            SecKeychainItemPassword {\n                data: data as *const _,\n                data_len: data_len as usize,\n            },\n            SecKeychainItem::wrap_under_create_rule(item),\n        ))\n    }\n}\n\nimpl SecKeychain {\n    /// Find application password in this keychain\n    #[inline]\n    pub fn find_generic_password(\n        &self,\n        service: &str,\n        account: &str,\n    ) -> Result<(SecKeychainItemPassword, SecKeychainItem)> {\n        find_generic_password(Some(std::slice::from_ref(self)), service, account)\n    }\n\n    /// Find internet password in this keychain\n    #[inline]\n    #[allow(clippy::too_many_arguments)]\n    pub fn find_internet_password(\n        &self,\n        server: &str,\n        security_domain: Option<&str>,\n        account: &str,\n        path: &str,\n        port: Option<u16>,\n        protocol: SecProtocolType,\n        authentication_type: SecAuthenticationType,\n    ) -> Result<(SecKeychainItemPassword, SecKeychainItem)> {\n        find_internet_password(\n            Some(std::slice::from_ref(self)),\n            server,\n            security_domain,\n            account,\n            path,\n            port,\n            protocol,\n            authentication_type,\n        )\n    }\n\n    /// Update existing or add new internet password\n    #[allow(clippy::too_many_arguments)]\n    pub fn set_internet_password(\n        &self,\n        server: &str,\n        security_domain: Option<&str>,\n        account: &str,\n        path: &str,\n        port: Option<u16>,\n        protocol: SecProtocolType,\n        authentication_type: SecAuthenticationType,\n        password: &[u8],\n    ) -> Result<()> {\n        match self.find_internet_password(\n            server,\n            security_domain,\n            account,\n            path,\n            port,\n            protocol,\n            authentication_type,\n        ) {\n            Ok((_, mut item)) => item.set_password(password),\n            _ => self.add_internet_password(\n                server,\n                security_domain,\n                account,\n                path,\n                port,\n                protocol,\n                authentication_type,\n                password,\n            ),\n        }\n    }\n\n    /// Set a generic password.\n    ///\n    /// * `keychain_opt` is the keychain to use or None to use the default keychain.\n    /// * `service` is the associated service name for the password.\n    /// * `account` is the associated account name for the password.\n    /// * `password` is the password itself.\n    pub fn set_generic_password(\n        &self,\n        service: &str,\n        account: &str,\n        password: &[u8],\n    ) -> Result<()> {\n        match self.find_generic_password(service, account) {\n            Ok((_, mut item)) => item.set_password(password),\n            _ => self.add_generic_password(service, account, password),\n        }\n    }\n\n    /// Add application password to the keychain, without checking if it exists already\n    ///\n    /// See `set_generic_password()`\n    #[inline]\n    pub fn add_generic_password(\n        &self,\n        service: &str,\n        account: &str,\n        password: &[u8],\n    ) -> Result<()> {\n        unsafe {\n            cvt(SecKeychainAddGenericPassword(\n                self.as_CFTypeRef() as *mut _,\n                service.len() as u32,\n                service.as_ptr().cast(),\n                account.len() as u32,\n                account.as_ptr().cast(),\n                password.len() as u32,\n                password.as_ptr().cast(),\n                ptr::null_mut(),\n            ))?;\n        }\n        Ok(())\n    }\n\n    /// Add internet password to the keychain, without checking if it exists already\n    ///\n    /// See `set_internet_password()`\n    #[inline]\n    #[allow(clippy::too_many_arguments)]\n    pub fn add_internet_password(\n        &self,\n        server: &str,\n        security_domain: Option<&str>,\n        account: &str,\n        path: &str,\n        port: Option<u16>,\n        protocol: SecProtocolType,\n        authentication_type: SecAuthenticationType,\n        password: &[u8],\n    ) -> Result<()> {\n        unsafe {\n            cvt(SecKeychainAddInternetPassword(\n                self.as_CFTypeRef() as *mut _,\n                server.len() as u32,\n                server.as_ptr().cast(),\n                security_domain.map_or(0, |s| s.len() as u32),\n                security_domain.map_or(ptr::null(), |s| s.as_ptr().cast()),\n                account.len() as u32,\n                account.as_ptr().cast(),\n                path.len() as u32,\n                path.as_ptr().cast(),\n                port.unwrap_or(0),\n                protocol,\n                authentication_type,\n                password.len() as u32,\n                password.as_ptr().cast(),\n                ptr::null_mut(),\n            ))?;\n        }\n        Ok(())\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use crate::os::macos::keychain::CreateOptions;\n    use tempfile::{tempdir, TempDir};\n\n    fn temp_keychain_setup(name: &str) -> (TempDir, SecKeychain) {\n        let dir = tempdir().expect(\"TempDir::new\");\n        let keychain = CreateOptions::new()\n            .password(\"foobar\")\n            .create(dir.path().join(name.to_string() + \".keychain\"))\n            .expect(\"create keychain\");\n\n        (dir, keychain)\n    }\n\n    fn temp_keychain_teardown(dir: TempDir) {\n        dir.close().expect(\"temp dir close\");\n    }\n\n    #[test]\n    fn missing_password_temp() {\n        let (dir, keychain) = temp_keychain_setup(\"missing_password\");\n        let keychains = vec![keychain];\n\n        let service = \"temp_this_service_does_not_exist\";\n        let account = \"this_account_is_bogus\";\n        let found = find_generic_password(Some(&keychains), service, account);\n\n        assert!(found.is_err());\n\n        temp_keychain_teardown(dir);\n    }\n\n    #[test]\n    fn default_keychain_test_missing_password_default() {\n        let service = \"default_this_service_does_not_exist\";\n        let account = \"this_account_is_bogus\";\n        let found = find_generic_password(None, service, account);\n\n        assert!(found.is_err());\n    }\n\n    #[test]\n    fn round_trip_password_temp() {\n        let (dir, keychain) = temp_keychain_setup(\"round_trip_password\");\n\n        let service = \"test_round_trip_password_temp\";\n        let account = \"temp_this_is_the_test_account\";\n        let password = String::from(\"deadbeef\").into_bytes();\n\n        keychain.set_generic_password(service, account, &password).expect(\"set_generic_password\");\n        let (found, item) = keychain.find_generic_password(service, account).expect(\"find_generic_password\");\n        assert_eq!(found.to_owned(), password);\n\n        item.delete();\n\n        temp_keychain_teardown(dir);\n    }\n\n    #[test]\n    fn default_keychain_test_round_trip_password_default() {\n        let service = \"test_round_trip_password_default\";\n        let account = \"this_is_the_test_account\";\n        let password = String::from(\"deadbeef\").into_bytes();\n\n        SecKeychain::default()\n            .expect(\"default keychain\")\n            .set_generic_password(service, account, &password)\n            .expect(\"set_generic_password\");\n        let (found, item) = find_generic_password(None, service, account).expect(\"find_generic_password\");\n        assert_eq!(&*found, &password[..]);\n\n        item.delete();\n    }\n\n    #[test]\n    fn change_password_temp() {\n        let (dir, keychain) = temp_keychain_setup(\"change_password\");\n        let keychains = vec![keychain];\n\n        let service = \"test_change_password_temp\";\n        let account = \"this_is_the_test_account\";\n        let pw1 = String::from(\"password1\").into_bytes();\n        let pw2 = String::from(\"password2\").into_bytes();\n\n        keychains[0]\n            .set_generic_password(service, account, &pw1)\n            .expect(\"set_generic_password1\");\n        let (found, _) = find_generic_password(Some(&keychains), service, account)\n            .expect(\"find_generic_password1\");\n        assert_eq!(found.as_ref(), &pw1[..]);\n\n        keychains[0]\n            .set_generic_password(service, account, &pw2)\n            .expect(\"set_generic_password2\");\n        let (found, item) = find_generic_password(Some(&keychains), service, account)\n            .expect(\"find_generic_password2\");\n        assert_eq!(&*found, &pw2[..]);\n\n        item.delete();\n\n        temp_keychain_teardown(dir);\n    }\n\n    #[test]\n    fn default_keychain_test_change_password_default() {\n        let service = \"test_change_password_default\";\n        let account = \"this_is_the_test_account\";\n        let pw1 = String::from(\"password1\").into_bytes();\n        let pw2 = String::from(\"password2\").into_bytes();\n\n        SecKeychain::default()\n            .expect(\"default keychain\")\n            .set_generic_password(service, account, &pw1)\n            .expect(\"set_generic_password1\");\n        let (found, _) = find_generic_password(None, service, account).expect(\"find_generic_password1\");\n        assert_eq!(found.to_owned(), pw1);\n\n        SecKeychain::default()\n            .expect(\"default keychain\")\n            .set_generic_password(service, account, &pw2)\n            .expect(\"set_generic_password2\");\n        let (found, item) = find_generic_password(None, service, account).expect(\"find_generic_password2\");\n        assert_eq!(found.to_owned(), pw2);\n\n        item.delete();\n    }\n\n    #[test]\n    fn cross_keychain_corruption_temp() {\n        let (dir1, keychain1) = temp_keychain_setup(\"cross_corrupt1\");\n        let (dir2, keychain2) = temp_keychain_setup(\"cross_corrupt2\");\n        let keychains1 = vec![keychain1.clone()];\n        let keychains2 = vec![keychain2.clone()];\n        let both_keychains = vec![keychain1, keychain2];\n\n        let service = \"temp_this_service_does_not_exist\";\n        let account = \"this_account_is_bogus\";\n        let password = String::from(\"deadbeef\").into_bytes();\n\n        // Make sure this password doesn't exist in either keychain.\n        let found = find_generic_password(Some(&both_keychains), service, account);\n        assert!(found.is_err());\n\n        // Set a password in one keychain.\n        keychains1[0]\n            .set_generic_password(service, account, &password)\n            .expect(\"set_generic_password\");\n\n        // Make sure it's found in that keychain.\n        let (found, item) = find_generic_password(Some(&keychains1), service, account)\n            .expect(\"find_generic_password1\");\n        assert_eq!(found.to_owned(), password);\n\n        // Make sure it's _not_ found in the other keychain.\n        let found = find_generic_password(Some(&keychains2), service, account);\n        assert!(found.is_err());\n\n        // Cleanup.\n        item.delete();\n\n        temp_keychain_teardown(dir1);\n        temp_keychain_teardown(dir2);\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/secure_transport.rs",
    "content": "//! OSX specific extensions to Secure Transport functionality.\n\nuse core_foundation::array::CFArray;\nuse core_foundation::base::TCFType;\nuse security_framework_sys::secure_transport::*;\nuse std::ptr;\nuse std::slice;\n\nuse crate::base::Result;\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::secure_transport::{MidHandshakeSslStream, SslContext};\n\n/// An extension trait adding OSX specific functionality to the `SslContext`\n/// type.\npub trait SslContextExt {\n    /// Returns the DER encoded data specifying the parameters used for\n    /// Diffie-Hellman key exchange.\n    fn diffie_hellman_params(&self) -> Result<Option<&[u8]>>;\n\n    /// Sets the parameters used for Diffie-Hellman key exchange, in the\n    /// DER format used by OpenSSL.\n    ///\n    /// If a cipher suite which uses Diffie-Hellman key exchange is selected,\n    /// parameters will automatically be generated if none are provided with\n    /// this method, but this process can take up to 30 seconds.\n    ///\n    /// This can only be called on server-side sessions.\n    fn set_diffie_hellman_params(&mut self, dh_params: &[u8]) -> Result<()>;\n\n    /// Returns the certificate authorities used to validate client\n    /// certificates.\n    fn certificate_authorities(&self) -> Result<Option<Vec<SecCertificate>>>;\n\n    /// Sets the certificate authorities used to validate client certificates,\n    /// replacing any that are already present.\n    fn set_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()>;\n\n    /// Adds certificate authorities used to validate client certificates.\n    fn add_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()>;\n\n    /// If enabled, server identity changes are allowed during renegotiation.\n    ///\n    /// It is disabled by default to protect against triple handshake attacks.\n    fn allow_server_identity_change(&self) -> Result<bool>;\n\n    /// If enabled, server identity changes are allowed during renegotiation.\n    ///\n    /// It is disabled by default to protect against triple handshake attacks.\n    #[deprecated(note = \"kSSLSessionOptionAllowServerIdentityChange is deprecated by Apple\")]\n    fn set_allow_server_identity_change(&mut self, value: bool) -> Result<()>;\n\n    /// If enabled, fallback countermeasures will be used during negotiation.\n    ///\n    /// It should be enabled when renegotiating with a peer with a lower\n    /// maximum protocol version due to an earlier failure to connect.\n    fn fallback(&self) -> Result<bool>;\n\n    /// If enabled, fallback countermeasures will be used during negotiation.\n    ///\n    /// It should be enabled when renegotiating with a peer with a lower\n    /// maximum protocol version due to an earlier failure to connect.\n    #[deprecated(note = \"kSSLSessionOptionFallback is deprecated by Apple\")]\n    fn set_fallback(&mut self, value: bool) -> Result<()>;\n\n    /// If enabled, the handshake process will pause and return when the client\n    /// hello is recieved to support server name identification.\n    fn break_on_client_hello(&self) -> Result<bool>;\n\n    /// If enabled, the handshake process will pause and return when the client\n    /// hello is recieved to support server name identification.\n    #[deprecated(note = \"kSSLSessionOptionBreakOnClientHello is deprecated by Apple\")]\n    fn set_break_on_client_hello(&mut self, value: bool) -> Result<()>;\n}\n\nmacro_rules! impl_options {\n    ($($(#[$a:meta])* const $opt:ident: $get:ident & $set:ident,)*) => {\n        $(\n            #[allow(deprecated)]\n            $(#[$a])*\n            #[inline]\n            fn $set(&mut self, value: bool) -> Result<()> {\n                unsafe {\n                    cvt(SSLSetSessionOption(self.as_inner(),\n                                            $opt,\n                                            ::core_foundation::base::Boolean::from(value)))\n                }\n            }\n\n            #[allow(deprecated)]\n            $(#[$a])*\n            #[inline]\n            fn $get(&self) -> Result<bool> {\n                let mut value = 0;\n                unsafe { cvt(SSLGetSessionOption(self.as_inner(), $opt, &mut value))?; }\n                Ok(value != 0)\n            }\n        )*\n    }\n}\n\nimpl SslContextExt for SslContext {\n    fn diffie_hellman_params(&self) -> Result<Option<&[u8]>> {\n        unsafe {\n            let mut ptr = ptr::null();\n            let mut len = 0;\n            cvt(SSLGetDiffieHellmanParams(\n                self.as_inner(),\n                &mut ptr,\n                &mut len,\n            ))?;\n            if ptr.is_null() {\n                Ok(None)\n            } else {\n                Ok(Some(slice::from_raw_parts(ptr.cast::<u8>(), len)))\n            }\n        }\n    }\n\n    fn set_diffie_hellman_params(&mut self, dh_params: &[u8]) -> Result<()> {\n        unsafe {\n            cvt(SSLSetDiffieHellmanParams(\n                self.as_inner(),\n                dh_params.as_ptr().cast(),\n                dh_params.len(),\n            ))\n        }\n    }\n\n    fn certificate_authorities(&self) -> Result<Option<Vec<SecCertificate>>> {\n        unsafe {\n            let mut raw_certs = ptr::null();\n            cvt(SSLCopyCertificateAuthorities(\n                self.as_inner(),\n                &mut raw_certs,\n            ))?;\n            if raw_certs.is_null() {\n                Ok(None)\n            } else {\n                let certs = CFArray::<SecCertificate>::wrap_under_create_rule(raw_certs)\n                    .iter()\n                    .map(|c| c.clone())\n                    .collect();\n                Ok(Some(certs))\n            }\n        }\n    }\n\n    fn set_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()> {\n        unsafe {\n            let certs = CFArray::from_CFTypes(certs);\n            cvt(SSLSetCertificateAuthorities(\n                self.as_inner(),\n                certs.as_CFTypeRef(),\n                1,\n            ))\n        }\n    }\n\n    fn add_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()> {\n        unsafe {\n            let certs = CFArray::from_CFTypes(certs);\n            cvt(SSLSetCertificateAuthorities(\n                self.as_inner(),\n                certs.as_CFTypeRef(),\n                0,\n            ))\n        }\n    }\n\n    impl_options! {\n        const kSSLSessionOptionAllowServerIdentityChange: allow_server_identity_change & set_allow_server_identity_change,\n        const kSSLSessionOptionFallback: fallback & set_fallback,\n        const kSSLSessionOptionBreakOnClientHello: break_on_client_hello & set_break_on_client_hello,\n    }\n}\n\n/// An extension trait adding OSX specific functionality to the\n/// `MidHandshakeSslStream` type.\npub trait MidHandshakeSslStreamExt {\n    /// Returns `true` iff `break_on_client_hello` was set and the handshake\n    /// has progressed to that point.\n    fn client_hello_received(&self) -> bool;\n}\n\nimpl<S> MidHandshakeSslStreamExt for MidHandshakeSslStream<S> {\n    fn client_hello_received(&self) -> bool {\n        self.error().code() == errSSLClientHelloReceived\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use std::io::prelude::*;\n    use std::net::{TcpListener, TcpStream};\n    use std::thread;\n    use tempfile::tempdir;\n\n    use super::*;\n    use crate::cipher_suite::CipherSuite;\n    use crate::os::macos::test::identity;\n    use crate::secure_transport::*;\n    use crate::test::ca_certificate;\n\n    #[test]\n    fn server_client() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n            let identity = identity(dir.path());\n            p!(ctx.set_certificate(&identity, &[]));\n\n            let stream = p!(listener.accept()).0;\n            let mut stream = p!(ctx.handshake(stream));\n\n            let mut buf = [0; 12];\n            p!(stream.read(&mut buf));\n            assert_eq!(&buf[..], b\"hello world!\");\n        });\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_break_on_server_auth(true));\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n\n        let stream = match ctx.handshake(stream) {\n            Ok(_) => panic!(\"unexpected success\"),\n            Err(HandshakeError::Interrupted(stream)) => stream,\n            Err(err) => panic!(\"unexpected error {err:?}\"),\n        };\n\n        assert!(stream.server_auth_completed());\n        let mut peer_trust = p!(stream.context().peer_trust2()).unwrap();\n        p!(peer_trust.set_anchor_certificates(&[ca_certificate()]));\n        p!(peer_trust.evaluate_with_error());\n\n        let mut stream = p!(stream.handshake());\n        p!(stream.write_all(b\"hello world!\"));\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn server_client_builders() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let identity = identity(dir.path());\n            let builder = ServerBuilder::new(&identity, &[]);\n\n            let stream = p!(listener.accept()).0;\n            let mut stream = p!(builder.handshake(stream));\n\n            let mut buf = [0; 12];\n            p!(stream.read(&mut buf));\n            assert_eq!(&buf[..], b\"hello world!\");\n        });\n\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n        let mut stream = p!(ClientBuilder::new()\n            .anchor_certificates(&[ca_certificate()])\n            .handshake(\"foobar.com\", stream));\n\n        p!(stream.write_all(b\"hello world!\"));\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn client_bad_cert() {\n        let _ = env_logger::try_init();\n\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n            let identity = identity(dir.path());\n            p!(ctx.set_certificate(&identity, &[]));\n\n            let stream = p!(listener.accept()).0;\n            let _ = ctx.handshake(stream);\n        });\n\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n        assert!(ClientBuilder::new().handshake(\"foobar.com\", stream).is_err());\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn client() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n            let identity = identity(dir.path());\n            p!(ctx.set_certificate(&identity, &[]));\n\n            let stream = p!(listener.accept()).0;\n            let mut stream = p!(ctx.handshake(stream));\n\n            let mut buf = [0; 12];\n            p!(stream.read(&mut buf));\n            assert_eq!(&buf[..], b\"hello world!\");\n        });\n\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n        let mut stream = p!(ClientBuilder::new()\n            .anchor_certificates(&[ca_certificate()])\n            .handshake(\"foobar.com\", stream));\n        p!(stream.write_all(b\"hello world!\"));\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn negotiated_cipher() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n            let identity = identity(dir.path());\n            p!(ctx.set_certificate(&identity, &[]));\n            p!(ctx.set_enabled_ciphers(&[\n                CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,\n                CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n            ]));\n\n            let stream = p!(listener.accept()).0;\n            let mut stream = p!(ctx.handshake(stream));\n            assert_eq!(\n                CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,\n                p!(stream.context().negotiated_cipher())\n            );\n            let mut buf = [0; 1];\n            p!(stream.read(&mut buf));\n        });\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_break_on_server_auth(true));\n        p!(ctx.set_enabled_ciphers(&[\n            CipherSuite::TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,\n            CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n        ]));\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n\n        let stream = match ctx.handshake(stream) {\n            Ok(_) => panic!(\"unexpected success\"),\n            Err(HandshakeError::Interrupted(stream)) => stream,\n            Err(err) => panic!(\"unexpected error {err:?}\"),\n        };\n\n        let mut stream = p!(stream.handshake());\n        assert_eq!(\n            CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,\n            p!(stream.context().negotiated_cipher())\n        );\n        p!(stream.write(&[0]));\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn dh_params() {\n        let params = include_bytes!(\"../../../test/dhparam.der\");\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n        assert!(p!(ctx.diffie_hellman_params()).is_none());\n        p!(ctx.set_diffie_hellman_params(params));\n        assert_eq!(p!(ctx.diffie_hellman_params()).unwrap(), &params[..]);\n    }\n\n    #[test]\n    fn try_authenticate_no_cert() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n            let identity = identity(dir.path());\n            p!(ctx.set_certificate(&identity, &[]));\n            p!(ctx.set_client_side_authenticate(SslAuthenticate::TRY));\n            let cert = ca_certificate();\n            p!(ctx.add_certificate_authorities(&[cert]));\n\n            let stream = p!(listener.accept()).0;\n            let mut stream = p!(ctx.handshake(stream));\n            let mut buf = [0; 1];\n            p!(stream.read(&mut buf));\n        });\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_break_on_server_auth(true));\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n\n        let stream = match ctx.handshake(stream) {\n            Ok(_) => panic!(\"unexpected success\"),\n            Err(HandshakeError::Interrupted(stream)) => stream,\n            Err(err) => panic!(\"unexpected error {err:?}\"),\n        };\n\n        let mut stream = p!(stream.handshake());\n        p!(stream.write(&[0]));\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn always_authenticate_no_cert() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n            let identity = identity(dir.path());\n            p!(ctx.set_certificate(&identity, &[]));\n            p!(ctx.set_client_side_authenticate(SslAuthenticate::ALWAYS));\n\n            let stream = p!(listener.accept()).0;\n\n            match ctx.handshake(stream) {\n                Ok(_) => panic!(\"unexpected success\"),\n                Err(HandshakeError::Failure(_)) => {},\n                Err(err) => panic!(\"unexpected error {err:?}\"),\n            }\n        });\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_break_on_server_auth(true));\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n\n        let stream = match ctx.handshake(stream) {\n            Ok(_) => panic!(\"unexpected success\"),\n            Err(HandshakeError::Interrupted(stream)) => stream,\n            Err(err) => panic!(\"unexpected error {err:?}\"),\n        };\n\n        match stream.handshake() {\n            Ok(_) => panic!(\"unexpected success\"),\n            Err(HandshakeError::Failure(_)) => {},\n            Err(err) => panic!(\"unexpected error {err:?}\"),\n        }\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn always_authenticate_with_cert() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n            let identity = identity(dir.path());\n            p!(ctx.set_certificate(&identity, &[]));\n            p!(ctx.set_client_side_authenticate(SslAuthenticate::ALWAYS));\n\n            let stream = p!(listener.accept()).0;\n\n            match ctx.handshake(stream) {\n                Ok(_) => panic!(\"unexpected success\"),\n                Err(HandshakeError::Failure(_)) => {},\n                Err(err) => panic!(\"unexpected error {err:?}\"),\n            }\n        });\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_break_on_server_auth(true));\n        let dir = p!(tempdir());\n        let identity = identity(dir.path());\n        p!(ctx.set_certificate(&identity, &[]));\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n\n        let stream = match ctx.handshake(stream) {\n            Ok(_) => panic!(\"unexpected success\"),\n            Err(HandshakeError::Interrupted(stream)) => stream,\n            Err(err) => panic!(\"unexpected error {err:?}\"),\n        };\n\n        match stream.handshake() {\n            Ok(_) => panic!(\"unexpected success\"),\n            Err(HandshakeError::Failure(_)) => {},\n            Err(err) => panic!(\"unexpected error {err:?}\"),\n        }\n\n        handle.join().unwrap();\n    }\n\n    #[test]\n    fn certificate_authorities() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n        assert!(p!(ctx.certificate_authorities()).is_none());\n        p!(ctx.set_certificate_authorities(&[ca_certificate()]));\n        assert_eq!(p!(ctx.certificate_authorities()).unwrap().len(), 1);\n    }\n\n    #[test]\n    fn close() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let identity = identity(dir.path());\n            let builder = ServerBuilder::new(&identity, &[]);\n\n            let stream = p!(listener.accept()).0;\n            let mut stream = p!(builder.handshake(stream));\n            p!(stream.close());\n        });\n\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n        let mut stream = p!(ClientBuilder::new()\n            .anchor_certificates(&[ca_certificate()])\n            .handshake(\"foobar.com\", stream));\n\n        let mut buf = [0; 1];\n        assert_eq!(p!(stream.read(&mut buf)), 0);\n        p!(stream.close());\n\n        p!(handle.join());\n    }\n\n    #[test]\n    fn short_read() {\n        let listener = p!(TcpListener::bind(\"localhost:0\"));\n        let port = p!(listener.local_addr()).port();\n\n        let handle = thread::spawn(move || {\n            let dir = p!(tempdir());\n\n            let identity = identity(dir.path());\n            let builder = ServerBuilder::new(&identity, &[]);\n\n            let stream = p!(listener.accept()).0;\n            let mut stream = p!(builder.handshake(stream));\n\n            stream.write_all(b\"hello\").unwrap();\n            // make sure stream doesn't close\n            stream\n        });\n\n        let stream = p!(TcpStream::connect((\"localhost\", port)));\n        let mut stream = p!(ClientBuilder::new()\n            .anchor_certificates(&[ca_certificate()])\n            .handshake(\"foobar.com\", stream));\n\n        let mut b = [0; 1];\n        stream.read_exact(&mut b).unwrap();\n        assert_eq!(stream.context().buffered_read_size().unwrap(), 4);\n        let mut b = [0; 5];\n        let read = stream.read(&mut b).unwrap();\n        assert_eq!(read, 4);\n\n        p!(handle.join());\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/macos/transform.rs",
    "content": "#![allow(deprecated)]\n//! Transform support. Deprecated by Apple.\nuse core_foundation::base::{CFType, TCFType};\nuse core_foundation::error::CFError;\nuse core_foundation::string::CFString;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse security_framework_sys::transform::*;\nuse std::ptr;\n\ndeclare_TCFType! {\n    /// A type representing a transform.\n    #[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\n    SecTransform, SecTransformRef\n}\nimpl_TCFType!(SecTransform, SecTransformRef, SecTransformGetTypeID);\n\nunsafe impl Sync for SecTransform {}\nunsafe impl Send for SecTransform {}\n\n#[allow(deprecated)]\nimpl SecTransform {\n    /// Sets an attribute of the transform.\n    pub fn set_attribute<T>(&mut self, key: &CFString, value: &T) -> Result<(), CFError>\n    where T: TCFType {\n        unsafe {\n            let mut error = ptr::null_mut();\n            SecTransformSetAttribute(\n                self.0,\n                key.as_concrete_TypeRef(),\n                value.as_CFTypeRef(),\n                &mut error,\n            );\n            if !error.is_null() {\n                return Err(CFError::wrap_under_create_rule(error));\n            }\n\n            Ok(())\n        }\n    }\n\n    /// Executes the transform.\n    ///\n    /// The return type depends on the type of transform.\n    // FIXME: deprecate and remove: don't expose CFType in Rust APIs.\n    pub fn execute(&mut self) -> Result<CFType, CFError> {\n        unsafe {\n            let mut error = ptr::null_mut();\n            let result = SecTransformExecute(self.0, &mut error);\n            if result.is_null() {\n                return Err(CFError::wrap_under_create_rule(error));\n            }\n\n            Ok(CFType::wrap_under_create_rule(result))\n        }\n    }\n}\n"
  },
  {
    "path": "security-framework/src/os/mod.rs",
    "content": "//! OS specific extensions.\n\n#[cfg(target_os = \"macos\")]\npub mod macos;\n"
  },
  {
    "path": "security-framework/src/passwords.rs",
    "content": "//! Support for password entries in the keychain.  Works on both iOS and macOS.\n//!\n//! If you want the extended keychain facilities only available on macOS, use the\n//! version of these functions in the macOS extensions module.\n\n#[doc(inline)]\npub use crate::passwords_options::{AccessControlOptions, PasswordOptions};\n\nuse crate::base::Result;\nuse crate::{cvt, Error};\nuse core_foundation::base::TCFType;\nuse core_foundation::boolean::CFBoolean;\nuse core_foundation::data::CFData;\nuse core_foundation::dictionary::CFDictionary;\nuse core_foundation_sys::base::{CFGetTypeID, CFRelease, CFTypeRef};\nuse core_foundation_sys::data::CFDataRef;\nuse security_framework_sys::base::{errSecDuplicateItem, errSecParam};\nuse security_framework_sys::item::{kSecReturnData, kSecValueData};\nuse security_framework_sys::keychain::{SecAuthenticationType, SecProtocolType};\nuse security_framework_sys::keychain_item::{\n    SecItemAdd, SecItemCopyMatching, SecItemDelete, SecItemUpdate,\n};\n\n/// Set a generic password for the given service and account.\n/// Creates or updates a keychain entry.\npub fn set_generic_password(service: &str, account: &str, password: &[u8]) -> Result<()> {\n    let mut options = PasswordOptions::new_generic_password(service, account);\n    set_password_internal(&mut options, password)\n}\n\n/// Set a generic password using the given password options.\n/// Creates or updates a keychain entry.\npub fn set_generic_password_options(password: &[u8], mut options: PasswordOptions) -> Result<()> {\n    set_password_internal(&mut options, password)\n}\n\n/// Get the generic password for the given service and account.  If no matching\n/// keychain entry exists, fails with error code `errSecItemNotFound`.\n#[doc(hidden)]\npub fn get_generic_password(service: &str, account: &str) -> Result<Vec<u8>> {\n    generic_password(PasswordOptions::new_generic_password(service, account))\n}\n\n/// Get the generic password for the given service and account.  If no matching\n/// keychain entry exists, fails with error code `errSecItemNotFound`.\n///\n/// See [`PasswordOptions`] and [`new_generic_password`](PasswordOptions::new_generic_password).\n///\n/// ```rust\n/// use security_framework::passwords::{generic_password, PasswordOptions};\n/// generic_password(PasswordOptions::new_generic_password(\"service\", \"account\"));\n/// ```\npub fn generic_password(mut options: PasswordOptions) -> Result<Vec<u8>> {\n    unsafe { options.push_query(kSecReturnData, CFBoolean::from(true)); }\n    let params = options.to_dictionary();\n    let mut ret: CFTypeRef = std::ptr::null();\n    cvt(unsafe { SecItemCopyMatching(params.as_concrete_TypeRef(), &mut ret) })?;\n    get_password_and_release(ret)\n}\n\n/// Delete the generic password keychain entry for the given service and account.\n/// If none exists, fails with error code `errSecItemNotFound`.\npub fn delete_generic_password(service: &str, account: &str) -> Result<()> {\n    let options = PasswordOptions::new_generic_password(service, account);\n    delete_generic_password_options(options)\n}\n\n/// Delete the generic password keychain entry for the given service and account.\n/// If none exists, fails with error code `errSecItemNotFound`.\n///\n/// See [`PasswordOptions`] and [`new_generic_password`](PasswordOptions::new_generic_password).\n///\n/// ```rust\n/// use security_framework::passwords::{delete_generic_password_options, PasswordOptions};\n/// delete_generic_password_options(PasswordOptions::new_generic_password(\"service\", \"account\"));\n/// ```\npub fn delete_generic_password_options(options: PasswordOptions) -> Result<()> {\n    let params = options.to_dictionary();\n    cvt(unsafe { SecItemDelete(params.as_concrete_TypeRef()) })\n}\n\n/// Set an internet password for the given endpoint parameters.\n/// Creates or updates a keychain entry.\n#[allow(clippy::too_many_arguments)]\npub fn set_internet_password(\n    server: &str,\n    security_domain: Option<&str>,\n    account: &str,\n    path: &str,\n    port: Option<u16>,\n    protocol: SecProtocolType,\n    authentication_type: SecAuthenticationType,\n    password: &[u8],\n) -> Result<()> {\n    let mut options = PasswordOptions::new_internet_password(\n        server,\n        security_domain,\n        account,\n        path,\n        port,\n        protocol,\n        authentication_type,\n    );\n    set_password_internal(&mut options, password)\n}\n\n/// Get the internet password for the given endpoint parameters.  If no matching\n/// keychain entry exists, fails with error code `errSecItemNotFound`.\npub fn get_internet_password(\n    server: &str,\n    security_domain: Option<&str>,\n    account: &str,\n    path: &str,\n    port: Option<u16>,\n    protocol: SecProtocolType,\n    authentication_type: SecAuthenticationType,\n) -> Result<Vec<u8>> {\n    let mut options = PasswordOptions::new_internet_password(\n        server,\n        security_domain,\n        account,\n        path,\n        port,\n        protocol,\n        authentication_type,\n    );\n    unsafe { options.push_query(kSecReturnData, CFBoolean::from(true)); }\n    let params = options.to_dictionary();\n    let mut ret: CFTypeRef = std::ptr::null();\n    cvt(unsafe { SecItemCopyMatching(params.as_concrete_TypeRef(), &mut ret) })?;\n    get_password_and_release(ret)\n}\n\n/// Delete the internet password for the given endpoint parameters.\n/// If none exists, fails with error code `errSecItemNotFound`.\npub fn delete_internet_password(\n    server: &str,\n    security_domain: Option<&str>,\n    account: &str,\n    path: &str,\n    port: Option<u16>,\n    protocol: SecProtocolType,\n    authentication_type: SecAuthenticationType,\n) -> Result<()> {\n    let options = PasswordOptions::new_internet_password(\n        server,\n        security_domain,\n        account,\n        path,\n        port,\n        protocol,\n        authentication_type,\n    );\n    let params = options.to_dictionary();\n    cvt(unsafe { SecItemDelete(params.as_concrete_TypeRef()) })\n}\n\n// This starts by trying to create the password with the given query params.\n// If the creation attempt reveals that one exists, its password is updated.\nfn set_password_internal(options: &mut PasswordOptions, password: &[u8]) -> Result<()> {\n    #[allow(deprecated)]\n    let query_without_password = options.query.len();\n    unsafe { options.push_query(kSecValueData, CFData::from_buffer(password)); }\n\n    let params = options.to_dictionary();\n    let mut ret = std::ptr::null();\n    let status = unsafe { SecItemAdd(params.as_concrete_TypeRef(), &mut ret) };\n    if status == errSecDuplicateItem {\n        #[allow(deprecated)]\n        let (query, pass) = options.query.split_at(query_without_password);\n        let params = CFDictionary::from_CFType_pairs(query);\n        let update = CFDictionary::from_CFType_pairs(pass);\n        cvt(unsafe { SecItemUpdate(params.as_concrete_TypeRef(), update.as_concrete_TypeRef()) })\n    } else {\n        cvt(status)\n    }\n}\n\n// Having retrieved a password entry, this copies and returns the password.\n//\n// # Safety\n// The data element passed in is assumed to have been returned from a Copy\n// call, so it's released after we are done with it.\nfn get_password_and_release(data: CFTypeRef) -> Result<Vec<u8>> {\n    if !data.is_null() {\n        let type_id = unsafe { CFGetTypeID(data) };\n        if type_id == CFData::type_id() {\n            let val = unsafe { CFData::wrap_under_create_rule(data as CFDataRef) };\n            let mut vec = Vec::new();\n            if !val.is_empty() {\n                vec.extend_from_slice(val.bytes());\n            }\n            return Ok(vec);\n        }\n        // unexpected: we got a reference to some other type.\n        // Release it to make sure there's no leak, but\n        // we can't return the password in this case.\n        unsafe { CFRelease(data) };\n    }\n    Err(Error::from_code(errSecParam))\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use security_framework_sys::base::errSecItemNotFound;\n\n    #[test]\n    fn missing_generic() {\n        let name = \"a string not likely to already be in the keychain as service or account\";\n        let result = delete_generic_password(name, name);\n        match result {\n            Ok(()) => (), // this is ok because the name _might_ be in the keychain\n            Err(err) if err.code() == errSecItemNotFound => (),\n            Err(err) => panic!(\"missing_generic: delete failed with status: {}\", err.code()),\n        }\n        let result = get_generic_password(name, name);\n        match result {\n            Ok(bytes) => panic!(\"missing_generic: get returned {bytes:?}\"),\n            Err(err) if err.code() == errSecItemNotFound => (),\n            Err(err) => panic!(\"missing_generic: get failed with status: {}\", err.code()),\n        }\n        let result = delete_generic_password(name, name);\n        match result {\n            Ok(()) => panic!(\"missing_generic: second delete found a password\"),\n            Err(err) if err.code() == errSecItemNotFound => (),\n            Err(err) => panic!(\"missing_generic: delete failed with status: {}\", err.code()),\n        }\n    }\n\n    #[test]\n    fn roundtrip_generic() {\n        let name = \"roundtrip_generic\";\n        set_generic_password(name, name, name.as_bytes()).expect(\"set_generic_password\");\n        let pass = get_generic_password(name, name).expect(\"get_generic_password\");\n        assert_eq!(name.as_bytes(), pass);\n        delete_generic_password(name, name).expect(\"delete_generic_password\");\n    }\n\n    #[test]\n    fn update_generic() {\n        let name = \"update_generic\";\n        set_generic_password(name, name, name.as_bytes()).expect(\"set_generic_password\");\n        let alternate = \"update_generic_alternate\";\n        set_generic_password(name, name, alternate.as_bytes()).expect(\"set_generic_password\");\n        let pass = get_generic_password(name, name).expect(\"get_generic_password\");\n        assert_eq!(pass, alternate.as_bytes());\n        delete_generic_password(name, name).expect(\"delete_generic_password\");\n    }\n\n    #[test]\n    fn missing_internet() {\n        let name = \"a string not likely to already be in the keychain as service or account\";\n        let (server, domain, account, path, port, protocol, auth) =\n            (name, None, name, \"/\", Some(8080u16), SecProtocolType::HTTP, SecAuthenticationType::Any);\n        let result = delete_internet_password(server, domain, account, path, port, protocol, auth);\n        match result {\n            Ok(()) => (), // this is ok because the name _might_ be in the keychain\n            Err(err) if err.code() == errSecItemNotFound => (),\n            Err(err) => panic!(\"missing_internet: delete failed with status: {}\", err.code()),\n        }\n        let result = get_internet_password(server, domain, account, path, port, protocol, auth);\n        match result {\n            Ok(bytes) => panic!(\"missing_internet: get returned {bytes:?}\"),\n            Err(err) if err.code() == errSecItemNotFound => (),\n            Err(err) => panic!(\"missing_internet: get failed with status: {}\", err.code()),\n        }\n        let result = delete_internet_password(server, domain, account, path, port, protocol, auth);\n        match result {\n            Ok(()) => panic!(\"missing_internet: second delete found a password\"),\n            Err(err) if err.code() == errSecItemNotFound => (),\n            Err(err) => panic!(\"missing_internet: delete failed with status: {}\", err.code()),\n        }\n    }\n\n    #[test]\n    fn roundtrip_internet() {\n        let name = \"roundtrip_internet\";\n        let (server, domain, account, path, port, protocol, auth) =\n            (name, None, name, \"/\", Some(8080u16), SecProtocolType::HTTP, SecAuthenticationType::Any);\n        set_internet_password(server, domain, account, path, port, protocol, auth, name.as_bytes())\n            .expect(\"set_internet_password\");\n        let pass =\n            get_internet_password(server, domain, account, path, port, protocol, auth).expect(\"get_internet_password\");\n        assert_eq!(name.as_bytes(), pass);\n        delete_internet_password(server, domain, account, path, port, protocol, auth)\n            .expect(\"delete_internet_password\");\n    }\n\n    #[test]\n    fn update_internet() {\n        let name = \"update_internet\";\n        let (server, domain, account, path, port, protocol, auth) =\n            (name, None, name, \"/\", Some(8080u16), SecProtocolType::HTTP, SecAuthenticationType::Any);\n\n        // cleanup after failed test\n        let _ = delete_internet_password(server, domain, account, path, port, protocol, auth);\n\n        set_internet_password(server, domain, account, path, port, protocol, auth, name.as_bytes())\n            .expect(\"set_internet_password\");\n        let alternate = \"alternate_internet_password\";\n        set_internet_password(server, domain, account, path, port, protocol, auth, alternate.as_bytes())\n            .expect(\"set_internet_password\");\n        let pass =\n            get_internet_password(server, domain, account, path, port, protocol, auth).expect(\"get_internet_password\");\n        assert_eq!(pass, alternate.as_bytes());\n        delete_internet_password(server, domain, account, path, port, protocol, auth)\n            .expect(\"delete_internet_password\");\n    }\n}\n"
  },
  {
    "path": "security-framework/src/passwords_options.rs",
    "content": "//! Support for password options, to be used with the passwords module\n\n// NB: re-export these types in the `passwords` module!\n\nuse crate::access_control::SecAccessControl;\nuse core_foundation::base::{CFOptionFlags, CFType, TCFType};\n#[allow(unused_imports)]\nuse core_foundation::boolean::CFBoolean;\nuse core_foundation::dictionary::CFDictionary;\nuse core_foundation::number::CFNumber;\nuse core_foundation::string::{CFString, CFStringRef};\nuse security_framework_sys::access_control::*;\nuse security_framework_sys::item::{\n    kSecAttrAccessControl, kSecAttrAccessGroup, kSecAttrAccount, kSecAttrAuthenticationType,\n    kSecAttrComment, kSecAttrDescription, kSecAttrLabel,\n    kSecAttrPath, kSecAttrPort, kSecAttrProtocol, kSecAttrSecurityDomain, kSecAttrServer,\n    kSecAttrService, kSecClass, kSecClassGenericPassword, kSecClassInternetPassword,\n};\nuse security_framework_sys::item::kSecAttrSynchronizable;\nuse security_framework_sys::item::kSecAttrSynchronizableAny;\n#[cfg(any(feature = \"OSX_10_15\", not(target_os = \"macos\")))]\nuse security_framework_sys::item::kSecUseDataProtectionKeychain;\nuse security_framework_sys::keychain::{SecAuthenticationType, SecProtocolType};\n\n/// `PasswordOptions` constructor\npub struct PasswordOptions {\n    /// query built for the keychain request\n    #[deprecated(note = \"This field should have been private. Please use setters that don't expose CFType\")]\n    pub query: Vec<(CFString, CFType)>,\n}\n\nbitflags::bitflags! {\n    /// The option flags used to configure the evaluation of a `SecAccessControl`.\n    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n    pub struct AccessControlOptions: CFOptionFlags {\n        /** Constraint to access an item with either biometry or passcode. */\n        const USER_PRESENCE = kSecAccessControlUserPresence;\n        /** Constraint to access an item with Touch ID for any enrolled fingers, or Face ID. */\n        const BIOMETRY_ANY = kSecAccessControlBiometryAny;\n        /** Constraint to access an item with Touch ID for currently enrolled fingers, or from Face ID with the currently enrolled user. */\n        const BIOMETRY_CURRENT_SET = kSecAccessControlBiometryCurrentSet;\n        /** Constraint to access an item with a passcode. */\n        const DEVICE_PASSCODE = kSecAccessControlDevicePasscode;\n        #[cfg(feature = \"OSX_10_15\")]\n        /** Constraint to access an item with a watch. */\n        const WATCH = kSecAccessControlWatch;\n        /** Indicates that at least one constraint must be satisfied. */\n        const OR = kSecAccessControlOr;\n        /** Indicates that all constraints must be satisfied. */\n        const AND = kSecAccessControlAnd;\n        /** Enable a private key to be used in signing a block of data or verifying a signed block. */\n        const PRIVATE_KEY_USAGE = kSecAccessControlPrivateKeyUsage;\n        /** Option to use an application-provided password for data encryption key generation. */\n        const APPLICATION_PASSWORD = kSecAccessControlApplicationPassword;\n    }\n}\n\nimpl PasswordOptions {\n    /// Create a new generic password options\n    /// Generic passwords are identified by service and account.  They have other\n    /// attributes, but this interface doesn't allow specifying them.\n    #[must_use]\n    pub fn new_generic_password(service: &str, account: &str) -> Self {\n        #[allow(deprecated)]\n        Self { query: vec![\n            (\n                unsafe { CFString::wrap_under_get_rule(kSecClass) },\n                unsafe { CFString::wrap_under_get_rule(kSecClassGenericPassword).into_CFType() },\n            ),\n            (unsafe { CFString::wrap_under_get_rule(kSecAttrService) }, CFString::from(service).into_CFType()),\n            (unsafe { CFString::wrap_under_get_rule(kSecAttrAccount) }, CFString::from(account).into_CFType()),\n        ] }\n    }\n\n    /// Create a new internet password options\n    /// Internet passwords are identified by a number of attributes.\n    /// They can have others, but this interface doesn't allow specifying them.\n    #[must_use]\n    pub fn new_internet_password(\n        server: &str,\n        security_domain: Option<&str>,\n        account: &str,\n        path: &str,\n        port: Option<u16>,\n        protocol: SecProtocolType,\n        authentication_type: SecAuthenticationType,\n    ) -> Self {\n        #[allow(deprecated)]\n        let mut this = Self { query: vec![\n            (\n                unsafe { CFString::wrap_under_get_rule(kSecClass) },\n                unsafe { CFString::wrap_under_get_rule(kSecClassInternetPassword) }.into_CFType(),\n            ),\n            (unsafe { CFString::wrap_under_get_rule(kSecAttrServer) }, CFString::from(server).into_CFType()),\n            (unsafe { CFString::wrap_under_get_rule(kSecAttrPath) }, CFString::from(path).into_CFType()),\n            (unsafe { CFString::wrap_under_get_rule(kSecAttrAccount) }, CFString::from(account).into_CFType()),\n            (unsafe { CFString::wrap_under_get_rule(kSecAttrProtocol) }, CFNumber::from(protocol as i32).into_CFType()),\n            (\n                unsafe { CFString::wrap_under_get_rule(kSecAttrAuthenticationType) },\n                CFNumber::from(authentication_type as i32).into_CFType(),\n            ),\n        ] };\n        if let Some(domain) = security_domain {\n            unsafe {\n                this.push_query(kSecAttrSecurityDomain, CFString::from(domain));\n            }\n        }\n        if let Some(port) = port {\n            unsafe {\n                this.push_query(kSecAttrPort, CFNumber::from(i32::from(port)));\n            }\n        }\n        this\n    }\n\n    /// Add access control to the password\n    pub fn set_access_control_options(&mut self, options: AccessControlOptions) {\n        unsafe {\n            self.push_query(kSecAttrAccessControl, SecAccessControl::create_with_flags(options.bits()).unwrap());\n        }\n    }\n\n    /// Add access control to the password\n    pub fn set_access_control(&mut self, access_control: SecAccessControl) {\n        unsafe {\n            self.push_query(kSecAttrAccessControl, access_control);\n        }\n    }\n\n    /// Add access group to the password\n    pub fn set_access_group(&mut self, group: &str) {\n        unsafe {\n            self.push_query(kSecAttrAccessGroup, CFString::from(group));\n        }\n    }\n\n    /// Specify whether password is cloud-synchronized, not cloud-synchronized, or either (`None`).\n    ///\n    /// Note: cloud-synchronized and not-cloud-synchronized passwords are kept\n    /// in completely different stores, so they are uniquely identified not just\n    /// by their `service` and `account` but also their cloud-synchronized option.\n    ///\n    /// If you specify a non-`None` value for this option, any operation you\n    /// perform - whether set, get, or delete - will only affect the store matching\n    /// the value: Some(`true`) will only affect the cloud-synchronized store and\n    /// Some(`false`) will only affect the not-cloud-synchronized store.\n    ///\n    /// If you specify `None` for this option, the effect depends on your operation:\n    ///\n    /// - Performing a delete will delete from both stores.\n    /// - Performing a get will return values from both stores, but since get only\n    ///   returns one value you can't be sure which store that value was in.\n    /// - Performing a set will update existing values in both stores. _But_, before\n    ///   doing any updates, set will first try to create a new value in the\n    ///   not-cloud-synchronized store (interpreting `None` as `false`). If\n    ///   that creation attempt succeeds, no update will be done of any existing\n    ///   value in the cloud-synchronized store. Thus, only if there is an existing\n    ///   value in the not-cloud-synchronized store will set update the\n    ///   cloud-synchronized store.\n    pub fn set_access_synchronized(&mut self, synchronized: Option<bool>) {\n        unsafe {\n            if let Some(synchronizable) = synchronized {\n                self.push_query(kSecAttrSynchronizable, CFBoolean::from(synchronizable));\n            } else {\n                let either = CFString::wrap_under_get_rule(kSecAttrSynchronizableAny);\n                self.push_query(kSecAttrSynchronizable, either);\n            }\n        }\n    }\n\n    /// Set the comment on the password\n    pub fn set_comment(&mut self, comment: &str) {\n        unsafe {\n            self.push_query(kSecAttrComment, CFString::from(comment));\n        }\n    }\n\n    /// Add a description to the password\n    pub fn set_description(&mut self, description: &str) {\n        unsafe {\n            self.push_query(kSecAttrDescription, CFString::from(description));\n        }\n    }\n\n    /// Add a label to the password\n    pub fn set_label(&mut self, label: &str) {\n        unsafe {\n            self.push_query(kSecAttrLabel, CFString::from(label));\n        }\n    }\n\n    #[cfg(any(feature = \"OSX_10_15\", not(target_os = \"macos\")))]\n    /// Use the data protection keychain (always true except on macOS)\n    pub fn use_protected_keychain(&mut self) {\n        unsafe {\n            self.push_query(kSecUseDataProtectionKeychain, CFBoolean::from(true));\n        }\n    }\n\n    /// The key must be a `kSec*` constant.\n    /// Value is any owned ObjC object, like `CFString`.\n    pub(crate) unsafe fn push_query(&mut self, static_key_constant: CFStringRef, value: impl TCFType) {\n        #[allow(deprecated)]\n        self.query.push((\n            unsafe { CFString::wrap_under_get_rule(static_key_constant) },\n            value.into_CFType(),\n        ));\n    }\n\n    pub(crate) fn to_dictionary(&self) -> CFDictionary<CFString, CFType> {\n        #[allow(deprecated)]\n        CFDictionary::from_CFType_pairs(&self.query[..])\n    }\n}\n"
  },
  {
    "path": "security-framework/src/policy.rs",
    "content": "//! Security Policies support.\nuse core_foundation::base::{CFOptionFlags, TCFType};\nuse core_foundation::string::CFString;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse security_framework_sys::base::{errSecParam, SecPolicyRef};\nuse security_framework_sys::policy::*;\nuse std::fmt;\nuse std::ptr;\n\nuse crate::secure_transport::SslProtocolSide;\nuse crate::Error;\n\ndeclare_TCFType! {\n    /// A type representing a certificate validation policy.\n    SecPolicy, SecPolicyRef\n}\nimpl_TCFType!(SecPolicy, SecPolicyRef, SecPolicyGetTypeID);\n\nunsafe impl Sync for SecPolicy {}\nunsafe impl Send for SecPolicy {}\n\nimpl fmt::Debug for SecPolicy {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"SecPolicy\").finish()\n    }\n}\n\nbitflags::bitflags! {\n    /// The flags used to specify revocation policy options.\n    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n    pub struct RevocationPolicy: CFOptionFlags {\n        /// Perform revocation checking using OCSP (Online Certificate Status Protocol).\n        const OCSP_METHOD = kSecRevocationOCSPMethod;\n        /// Perform revocation checking using the CRL (Certification Revocation List) method.\n        const CRL_METHOD = kSecRevocationCRLMethod;\n        /// Prefer CRL revocation checking over OCSP; by default, OCSP is preferred.\n        const PREFER_CRL = kSecRevocationPreferCRL;\n        /// Require a positive response to pass the policy.\n        const REQUIRE_POSITIVE_RESPONSE = kSecRevocationRequirePositiveResponse;\n        /// Consult only locally cached replies; do not use network access.\n        const NETWORK_ACCESS_DISABLED = kSecRevocationNetworkAccessDisabled;\n        /// Perform either OCSP or CRL checking.\n        const USE_ANY_METHOD_AVAILABLE = kSecRevocationUseAnyAvailableMethod;\n    }\n}\n\nimpl SecPolicy {\n    /// Creates a `SecPolicy` for evaluating SSL certificate chains.\n    ///\n    /// The side which you are evaluating should be provided (i.e. pass `SslSslProtocolSide::SERVER` if\n    /// you are a client looking to validate a server's certificate chain).\n    pub fn create_ssl(protocol_side: SslProtocolSide, hostname: Option<&str>) -> Self {\n        let hostname = hostname.map(CFString::new);\n        let hostname = hostname\n            .as_ref()\n            .map(|s| s.as_concrete_TypeRef())\n            .unwrap_or(ptr::null_mut());\n        let is_server = protocol_side == SslProtocolSide::SERVER;\n        unsafe {\n            let policy = SecPolicyCreateSSL(is_server.into(), hostname);\n            Self::wrap_under_create_rule(policy)\n        }\n    }\n\n    /// Creates a `SecPolicy` for checking revocation of certificates.\n    ///\n    /// If you do not specify this policy creating a `SecTrust` object, the system defaults\n    /// will be used during evaluation.\n    pub fn create_revocation(options: RevocationPolicy) -> crate::Result<Self> {\n        let policy = unsafe { SecPolicyCreateRevocation(options.bits()) };\n\n        if policy.is_null() {\n            Err(Error::from_code(errSecParam))\n        } else {\n            Ok(unsafe { Self::wrap_under_create_rule(policy) })\n        }\n    }\n\n    /// Returns a policy object for the default X.509 policy.\n    #[must_use]\n    pub fn create_x509() -> Self {\n        unsafe {\n            let policy = SecPolicyCreateBasicX509();\n            Self::wrap_under_create_rule(policy)\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use crate::policy::SecPolicy;\n    use crate::secure_transport::SslProtocolSide;\n\n    #[test]\n    fn create_ssl() {\n        SecPolicy::create_ssl(SslProtocolSide::SERVER, Some(\"certifi.org\"));\n    }\n}\n"
  },
  {
    "path": "security-framework/src/random.rs",
    "content": "//! Randomness support.\n\nuse security_framework_sys::random::{kSecRandomDefault, SecRandomCopyBytes, SecRandomRef};\nuse std::io;\n\n/// A source of random data.\npub struct SecRandom(SecRandomRef);\n\nunsafe impl Sync for SecRandom {}\nunsafe impl Send for SecRandom {}\n\nimpl Default for SecRandom {\n    #[inline(always)]\n    fn default() -> Self {\n        unsafe { Self(kSecRandomDefault) }\n    }\n}\n\nimpl SecRandom {\n    /// Fills the buffer with cryptographically secure random bytes.\n    pub fn copy_bytes(&self, buf: &mut [u8]) -> io::Result<()> {\n        if unsafe { SecRandomCopyBytes(self.0, buf.len(), buf.as_mut_ptr().cast()) } == 0 {\n            Ok(())\n        } else {\n            Err(io::Error::last_os_error())\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n\n    #[test]\n    fn basic() {\n        let mut buf = [0; 10];\n        SecRandom::default().copy_bytes(&mut buf).unwrap();\n    }\n}\n"
  },
  {
    "path": "security-framework/src/secure_transport.rs",
    "content": "//! SSL/TLS encryption support using Secure Transport.\n//!\n//! # Examples\n//!\n//! To connect as a client to a server with a certificate trusted by the system:\n//!\n//! ```rust\n//! use security_framework::secure_transport::ClientBuilder;\n//! use std::io::prelude::*;\n//! use std::net::TcpStream;\n//!\n//! let stream = TcpStream::connect(\"google.com:443\").unwrap();\n//! let mut stream = ClientBuilder::new().handshake(\"google.com\", stream).unwrap();\n//!\n//! stream.write_all(b\"GET / HTTP/1.0\\r\\n\\r\\n\").unwrap();\n//! let mut page = vec![];\n//! stream.read_to_end(&mut page).unwrap();\n//! println!(\"{}\", String::from_utf8_lossy(&page));\n//! ```\n//!\n//! To connect to a server with a certificate that's *not* trusted by the\n//! system, specify the root certificates for the server's chain to the\n//! `ClientBuilder`:\n//!\n//! ```rust,no_run\n//! use security_framework::secure_transport::ClientBuilder;\n//! use std::io::prelude::*;\n//! use std::net::TcpStream;\n//!\n//! # let root_cert = unsafe { std::mem::zeroed() };\n//! let stream = TcpStream::connect(\"my_server.com:443\").unwrap();\n//! let mut stream = ClientBuilder::new()\n//!     .anchor_certificates(&[root_cert])\n//!     .handshake(\"my_server.com\", stream)\n//!     .unwrap();\n//!\n//! stream.write_all(b\"GET / HTTP/1.0\\r\\n\\r\\n\").unwrap();\n//! let mut page = vec![];\n//! stream.read_to_end(&mut page).unwrap();\n//! println!(\"{}\", String::from_utf8_lossy(&page));\n//! ```\n//!\n//! For more advanced configuration, the `SslContext` type can be used directly.\n//!\n//! To run a server:\n//!\n//! ```rust,no_run\n//! use security_framework::secure_transport::{SslConnectionType, SslContext, SslProtocolSide};\n//! use std::net::TcpListener;\n//! use std::thread;\n//!\n//! // Create a TCP listener and start accepting on it.\n//! let mut listener = TcpListener::bind(\"0.0.0.0:443\").unwrap();\n//!\n//! for stream in listener.incoming() {\n//!     let stream = stream.unwrap();\n//!     thread::spawn(move || {\n//!         // Create a new context configured to operate on the server side of\n//!         // a traditional SSL/TLS session.\n//!         let mut ctx = SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM)\n//!                           .unwrap();\n//!\n//!         // Install the certificate chain that we will be using.\n//!         # let identity = unsafe { std::mem::zeroed() };\n//!         # let intermediate_cert = unsafe { std::mem::zeroed() };\n//!         # let root_cert = unsafe { std::mem::zeroed() };\n//!         ctx.set_certificate(identity, &[intermediate_cert, root_cert]).unwrap();\n//!\n//!         // Perform the SSL/TLS handshake and get our stream.\n//!         let mut stream = ctx.handshake(stream).unwrap();\n//!     });\n//! }\n//! ```\n#![allow(clippy::result_large_err)]\n#[allow(unused_imports)]\nuse core_foundation::array::{CFArray, CFArrayRef};\nuse core_foundation::base::{Boolean, TCFType};\nuse core_foundation::string::CFString;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse core_foundation_sys::base::{kCFAllocatorDefault, OSStatus};\nuse std::os::raw::c_void;\n\n#[allow(unused_imports)]\nuse security_framework_sys::base::{\n    errSecBadReq, errSecIO, errSecNotTrusted, errSecSuccess, errSecTrustSettingDeny,\n    errSecUnimplemented,\n};\n\nuse security_framework_sys::secure_transport::*;\nuse std::any::Any;\nuse std::cmp;\nuse std::fmt;\nuse std::io;\nuse std::io::prelude::*;\nuse std::marker::PhantomData;\nuse std::panic::{self, AssertUnwindSafe};\nuse std::ptr;\nuse std::result;\nuse std::slice;\n\nuse crate::base::{Error, Result};\nuse crate::certificate::SecCertificate;\nuse crate::cipher_suite::CipherSuite;\nuse crate::cvt;\nuse crate::identity::SecIdentity;\nuse crate::import_export::Pkcs12ImportOptions;\nuse crate::policy::SecPolicy;\nuse crate::trust::SecTrust;\nuse security_framework_sys::base::errSecParam;\n\n/// Specifies a side of a TLS session.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub struct SslProtocolSide(SSLProtocolSide);\n\nimpl SslProtocolSide {\n    /// The client side of the session.\n    pub const CLIENT: Self = Self(kSSLClientSide);\n    /// The server side of the session.\n    pub const SERVER: Self = Self(kSSLServerSide);\n}\n\n/// Specifies the type of TLS session.\n#[derive(Debug, Copy, Clone)]\npub struct SslConnectionType(SSLConnectionType);\n\nimpl SslConnectionType {\n    /// A DTLS session.\n    pub const DATAGRAM: Self = Self(kSSLDatagramType);\n    /// A traditional TLS stream.\n    pub const STREAM: Self = Self(kSSLStreamType);\n}\n\n/// An error or intermediate state after a TLS handshake attempt.\n#[derive(Debug)]\npub enum HandshakeError<S> {\n    /// The handshake failed.\n    Failure(Error),\n    /// The handshake was interrupted midway through.\n    Interrupted(MidHandshakeSslStream<S>),\n}\n\nimpl<S> From<Error> for HandshakeError<S> {\n    #[inline(always)]\n    fn from(err: Error) -> Self {\n        Self::Failure(err)\n    }\n}\n\n/// An error or intermediate state after a TLS handshake attempt.\n#[derive(Debug)]\npub enum ClientHandshakeError<S> {\n    /// The handshake failed.\n    Failure(Error),\n    /// The handshake was interrupted midway through.\n    Interrupted(MidHandshakeClientBuilder<S>),\n}\n\nimpl<S> From<Error> for ClientHandshakeError<S> {\n    #[inline(always)]\n    fn from(err: Error) -> Self {\n        Self::Failure(err)\n    }\n}\n\n/// An SSL stream midway through the handshake process.\n#[derive(Debug)]\npub struct MidHandshakeSslStream<S> {\n    stream: SslStream<S>,\n    error: Error,\n}\n\nimpl<S> MidHandshakeSslStream<S> {\n    /// Returns a shared reference to the inner stream.\n    #[inline(always)]\n    #[must_use]\n    pub fn get_ref(&self) -> &S {\n        self.stream.get_ref()\n    }\n\n    /// Returns a mutable reference to the inner stream.\n    #[inline(always)]\n    pub fn get_mut(&mut self) -> &mut S {\n        self.stream.get_mut()\n    }\n\n    /// Returns a shared reference to the `SslContext` of the stream.\n    #[inline(always)]\n    #[must_use]\n    pub fn context(&self) -> &SslContext {\n        self.stream.context()\n    }\n\n    /// Returns a mutable reference to the `SslContext` of the stream.\n    #[inline(always)]\n    pub fn context_mut(&mut self) -> &mut SslContext {\n        self.stream.context_mut()\n    }\n\n    /// Returns `true` iff `break_on_server_auth` was set and the handshake has\n    /// progressed to that point.\n    #[inline(always)]\n    #[must_use]\n    pub fn server_auth_completed(&self) -> bool {\n        self.error.code() == errSSLPeerAuthCompleted\n    }\n\n    /// Returns `true` iff `break_on_cert_requested` was set and the handshake\n    /// has progressed to that point.\n    #[inline(always)]\n    #[must_use]\n    pub fn client_cert_requested(&self) -> bool {\n        self.error.code() == errSSLClientCertRequested\n    }\n\n    /// Returns `true` iff the underlying stream returned an error with the\n    /// `WouldBlock` kind.\n    #[inline(always)]\n    #[must_use]\n    pub fn would_block(&self) -> bool {\n        self.error.code() == errSSLWouldBlock\n    }\n\n    /// Returns the error which caused the handshake interruption.\n    #[inline(always)]\n    #[must_use]\n    pub const fn error(&self) -> &Error {\n        &self.error\n    }\n\n    /// Restarts the handshake process.\n    #[inline(always)]\n    pub fn handshake(self) -> result::Result<SslStream<S>, HandshakeError<S>> {\n        self.stream.handshake()\n    }\n}\n\n/// An SSL stream midway through the handshake process.\n#[derive(Debug)]\npub struct MidHandshakeClientBuilder<S> {\n    stream: MidHandshakeSslStream<S>,\n    domain: Option<String>,\n    certs: Vec<SecCertificate>,\n    trust_certs_only: bool,\n    danger_accept_invalid_certs: bool,\n}\n\nimpl<S> MidHandshakeClientBuilder<S> {\n    /// Returns a shared reference to the inner stream.\n    #[inline(always)]\n    #[must_use]\n    pub fn get_ref(&self) -> &S {\n        self.stream.get_ref()\n    }\n\n    /// Returns a mutable reference to the inner stream.\n    #[inline(always)]\n    pub fn get_mut(&mut self) -> &mut S {\n        self.stream.get_mut()\n    }\n\n    /// Returns the error which caused the handshake interruption.\n    #[inline(always)]\n    #[must_use]\n    pub fn error(&self) -> &Error {\n        self.stream.error()\n    }\n\n    /// Restarts the handshake process.\n    pub fn handshake(self) -> result::Result<SslStream<S>, ClientHandshakeError<S>> {\n        let Self {\n            stream,\n            domain,\n            certs,\n            trust_certs_only,\n            danger_accept_invalid_certs,\n        } = self;\n\n        let mut result = stream.handshake();\n        loop {\n            let stream = match result {\n                Ok(stream) => return Ok(stream),\n                Err(HandshakeError::Interrupted(stream)) => stream,\n                Err(HandshakeError::Failure(err)) => return Err(ClientHandshakeError::Failure(err)),\n            };\n\n            if stream.would_block() {\n                let ret = Self {\n                    stream,\n                    domain,\n                    certs,\n                    trust_certs_only,\n                    danger_accept_invalid_certs,\n                };\n                return Err(ClientHandshakeError::Interrupted(ret));\n            }\n\n            if stream.server_auth_completed() {\n                if danger_accept_invalid_certs {\n                    result = stream.handshake();\n                    continue;\n                }\n                let Some(mut trust) = stream.context().peer_trust2()? else {\n                    result = stream.handshake();\n                    continue;\n                };\n                trust.set_anchor_certificates(&certs)?;\n                trust.set_trust_anchor_certificates_only(self.trust_certs_only)?;\n                let policy = SecPolicy::create_ssl(SslProtocolSide::SERVER, domain.as_deref());\n                trust.set_policy(&policy)?;\n                trust.evaluate_with_error().map_err(|error| {\n                    #[cfg(feature = \"log\")]\n                    log::warn!(\"SecTrustEvaluateWithError: {error}\");\n                    Error::from_code(error.code() as _)\n                })?;\n                result = stream.handshake();\n                continue;\n            }\n\n            let err = Error::from_code(stream.error().code());\n            return Err(ClientHandshakeError::Failure(err));\n        }\n    }\n}\n\n/// Specifies the state of a TLS session.\n#[derive(Debug, PartialEq, Eq)]\npub struct SessionState(SSLSessionState);\n\nimpl SessionState {\n    /// The session has been aborted due to an error.\n    pub const ABORTED: Self = Self(kSSLAborted);\n    /// The session has been terminated.\n    pub const CLOSED: Self = Self(kSSLClosed);\n    /// The session is connected.\n    pub const CONNECTED: Self = Self(kSSLConnected);\n    /// The session is in the handshake process.\n    pub const HANDSHAKE: Self = Self(kSSLHandshake);\n    /// The session has not yet started.\n    pub const IDLE: Self = Self(kSSLIdle);\n}\n\n/// Specifies a server's requirement for client certificates.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub struct SslAuthenticate(SSLAuthenticate);\n\nimpl SslAuthenticate {\n    /// Require a client certificate.\n    pub const ALWAYS: Self = Self(kAlwaysAuthenticate);\n    /// Do not request a client certificate.\n    pub const NEVER: Self = Self(kNeverAuthenticate);\n    /// Request but do not require a client certificate.\n    pub const TRY: Self = Self(kTryAuthenticate);\n}\n\n/// Specifies the state of client certificate processing.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub struct SslClientCertificateState(SSLClientCertificateState);\n\nimpl SslClientCertificateState {\n    /// A client certificate has not been requested or sent.\n    pub const NONE: Self = Self(kSSLClientCertNone);\n    /// A client certificate has been received but has failed to validate.\n    pub const REJECTED: Self = Self(kSSLClientCertRejected);\n    /// A client certificate has been requested but not recieved.\n    pub const REQUESTED: Self = Self(kSSLClientCertRequested);\n    /// A client certificate has been received and successfully validated.\n    pub const SENT: Self = Self(kSSLClientCertSent);\n}\n\n/// Specifies protocol versions.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub struct SslProtocol(SSLProtocol);\n\nimpl SslProtocol {\n    /// All supported TLS/SSL versions are accepted.\n    pub const ALL: Self = Self(kSSLProtocolAll);\n    /// The `DTLSv1` protocol is preferred.\n    pub const DTLS1: Self = Self(kDTLSProtocol1);\n    /// Only the SSL 2.0 protocol is accepted.\n    pub const SSL2: Self = Self(kSSLProtocol2);\n    /// The SSL 3.0 protocol is preferred, though SSL 2.0 may be used if the peer does not support\n    /// SSL 3.0.\n    pub const SSL3: Self = Self(kSSLProtocol3);\n    /// Only the SSL 3.0 protocol is accepted.\n    pub const SSL3_ONLY: Self = Self(kSSLProtocol3Only);\n    /// The TLS 1.0 protocol is preferred, though lower versions may be used\n    /// if the peer does not support TLS 1.0.\n    pub const TLS1: Self = Self(kTLSProtocol1);\n    /// The TLS 1.1 protocol is preferred, though lower versions may be used\n    /// if the peer does not support TLS 1.1.\n    pub const TLS11: Self = Self(kTLSProtocol11);\n    /// The TLS 1.2 protocol is preferred, though lower versions may be used\n    /// if the peer does not support TLS 1.2.\n    pub const TLS12: Self = Self(kTLSProtocol12);\n    /// The TLS 1.3 protocol is preferred, though lower versions may be used\n    /// if the peer does not support TLS 1.3.\n    pub const TLS13: Self = Self(kTLSProtocol13);\n    /// Only the TLS 1.0 protocol is accepted.\n    pub const TLS1_ONLY: Self = Self(kTLSProtocol1Only);\n    /// No protocol has been or should be negotiated or specified; use the default.\n    pub const UNKNOWN: Self = Self(kSSLProtocolUnknown);\n}\n\ndeclare_TCFType! {\n    /// A Secure Transport SSL/TLS context object.\n    SslContext, SSLContextRef\n}\n\nimpl_TCFType!(SslContext, SSLContextRef, SSLContextGetTypeID);\n\nimpl fmt::Debug for SslContext {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let mut builder = fmt.debug_struct(\"SslContext\");\n        if let Ok(state) = self.state() {\n            builder.field(\"state\", &state);\n        }\n        builder.finish()\n    }\n}\n\nunsafe impl Sync for SslContext {}\nunsafe impl Send for SslContext {}\n\n#[cfg(target_os = \"macos\")]\nimpl SslContext {\n    pub(crate) fn as_inner(&self) -> SSLContextRef {\n        self.0\n    }\n}\n\nmacro_rules! impl_options {\n    ($($(#[$a:meta])* const $opt:ident: $get:ident & $set:ident,)*) => {\n        $(\n            #[allow(deprecated)]\n            $(#[$a])*\n            #[inline(always)]\n            pub fn $set(&mut self, value: bool) -> Result<()> {\n                unsafe { cvt(SSLSetSessionOption(self.0, $opt, Boolean::from(value))) }\n            }\n\n            #[allow(deprecated)]\n            $(#[$a])*\n            #[inline]\n            pub fn $get(&self) -> Result<bool> {\n                let mut value = 0;\n                unsafe { cvt(SSLGetSessionOption(self.0, $opt, &mut value))?; }\n                Ok(value != 0)\n            }\n        )*\n    }\n}\n\nimpl SslContext {\n    /// Creates a new `SslContext` for the specified side and type of SSL\n    /// connection.\n    #[inline]\n    pub fn new(side: SslProtocolSide, type_: SslConnectionType) -> Result<Self> {\n        unsafe {\n            let ctx = SSLCreateContext(kCFAllocatorDefault, side.0, type_.0);\n            Ok(Self(ctx))\n        }\n    }\n\n    /// Sets the fully qualified domain name of the peer.\n    ///\n    /// This will be used on the client side of a session to validate the\n    /// common name field of the server's certificate. It has no effect if\n    /// called on a server-side `SslContext`.\n    ///\n    /// It is *highly* recommended to call this method before starting the\n    /// handshake process.\n    #[inline]\n    pub fn set_peer_domain_name(&mut self, peer_name: &str) -> Result<()> {\n        unsafe {\n            // SSLSetPeerDomainName doesn't need a null terminated string\n            cvt(SSLSetPeerDomainName(self.0, peer_name.as_ptr().cast(), peer_name.len()))\n        }\n    }\n\n    /// Returns the peer domain name set by `set_peer_domain_name`.\n    pub fn peer_domain_name(&self) -> Result<String> {\n        unsafe {\n            let mut len = 0;\n            cvt(SSLGetPeerDomainNameLength(self.0, &mut len))?;\n            let mut buf = vec![0; len];\n            cvt(SSLGetPeerDomainName(self.0, buf.as_mut_ptr().cast(), &mut len))?;\n            String::from_utf8(buf).map_err(|_| Error::from_code(-1))\n        }\n    }\n\n    /// Sets the certificate to be used by this side of the SSL session.\n    ///\n    /// This must be called before the handshake for server-side connections,\n    /// and can be used on the client-side to specify a client certificate.\n    ///\n    /// The `identity` corresponds to the leaf certificate and private\n    /// key, and the `certs` correspond to extra certificates in the chain.\n    pub fn set_certificate(\n        &mut self,\n        identity: &SecIdentity,\n        certs: &[SecCertificate],\n    ) -> Result<()> {\n        let mut arr = vec![identity.as_CFType()];\n        arr.extend(certs.iter().map(|c| c.as_CFType()));\n        let certs = CFArray::from_CFTypes(&arr);\n\n        unsafe { cvt(SSLSetCertificate(self.0, certs.as_concrete_TypeRef())) }\n    }\n\n    /// Sets the peer ID of this session.\n    ///\n    /// A peer ID is an opaque sequence of bytes that will be used by Secure\n    /// Transport to identify the peer of an SSL session. If the peer ID of\n    /// this session matches that of a previously terminated session, the\n    /// previous session can be resumed without requiring a full handshake.\n    #[inline]\n    pub fn set_peer_id(&mut self, peer_id: &[u8]) -> Result<()> {\n        unsafe { cvt(SSLSetPeerID(self.0, peer_id.as_ptr().cast(), peer_id.len())) }\n    }\n\n    /// Returns the peer ID of this session.\n    pub fn peer_id(&self) -> Result<Option<&[u8]>> {\n        unsafe {\n            let mut ptr = ptr::null();\n            let mut len = 0;\n            cvt(SSLGetPeerID(self.0, &mut ptr, &mut len))?;\n            if ptr.is_null() {\n                Ok(None)\n            } else {\n                Ok(Some(slice::from_raw_parts(ptr.cast(), len)))\n            }\n        }\n    }\n\n    /// Returns the list of ciphers that are supported by Secure Transport.\n    pub fn supported_ciphers(&self) -> Result<Vec<CipherSuite>> {\n        unsafe {\n            let mut num_ciphers = 0;\n            cvt(SSLGetNumberSupportedCiphers(self.0, &mut num_ciphers))?;\n            let mut ciphers = vec![0; num_ciphers];\n            cvt(SSLGetSupportedCiphers(\n                self.0,\n                ciphers.as_mut_ptr(),\n                &mut num_ciphers,\n            ))?;\n            Ok(ciphers.iter().map(|c| CipherSuite::from_raw(*c)).collect())\n        }\n    }\n\n    /// Returns the list of ciphers that are eligible to be used for\n    /// negotiation.\n    pub fn enabled_ciphers(&self) -> Result<Vec<CipherSuite>> {\n        unsafe {\n            let mut num_ciphers = 0;\n            cvt(SSLGetNumberEnabledCiphers(self.0, &mut num_ciphers))?;\n            let mut ciphers = vec![0; num_ciphers];\n            cvt(SSLGetEnabledCiphers(\n                self.0,\n                ciphers.as_mut_ptr(),\n                &mut num_ciphers,\n            ))?;\n            Ok(ciphers.iter().map(|c| CipherSuite::from_raw(*c)).collect())\n        }\n    }\n\n    /// Sets the list of ciphers that are eligible to be used for negotiation.\n    pub fn set_enabled_ciphers(&mut self, ciphers: &[CipherSuite]) -> Result<()> {\n        let ciphers = ciphers.iter().map(|c| c.to_raw()).collect::<Vec<_>>();\n        unsafe {\n            cvt(SSLSetEnabledCiphers(\n                self.0,\n                ciphers.as_ptr(),\n                ciphers.len(),\n            ))\n        }\n    }\n\n    /// Returns the cipher being used by the session.\n    #[inline]\n    pub fn negotiated_cipher(&self) -> Result<CipherSuite> {\n        unsafe {\n            let mut cipher = 0;\n            cvt(SSLGetNegotiatedCipher(self.0, &mut cipher))?;\n            Ok(CipherSuite::from_raw(cipher))\n        }\n    }\n\n    /// Sets the requirements for client certificates.\n    ///\n    /// Should only be called on server-side sessions.\n    #[inline]\n    pub fn set_client_side_authenticate(&mut self, auth: SslAuthenticate) -> Result<()> {\n        unsafe { cvt(SSLSetClientSideAuthenticate(self.0, auth.0)) }\n    }\n\n    /// Returns the state of client certificate processing.\n    #[inline]\n    pub fn client_certificate_state(&self) -> Result<SslClientCertificateState> {\n        let mut state = 0;\n\n        unsafe {\n            cvt(SSLGetClientCertificateState(self.0, &mut state))?;\n        }\n        Ok(SslClientCertificateState(state))\n    }\n\n    /// Returns the `SecTrust` object corresponding to the peer.\n    ///\n    /// This can be used in conjunction with `set_break_on_server_auth` to\n    /// validate certificates which do not have roots in the default set.\n    pub fn peer_trust2(&self) -> Result<Option<SecTrust>> {\n        // Calling SSLCopyPeerTrust on an idle connection does not seem to be well defined,\n        // so explicitly check for that\n        if self.state()? == SessionState::IDLE {\n            return Err(Error::from_code(errSecBadReq));\n        }\n\n        unsafe {\n            let mut trust = ptr::null_mut();\n            cvt(SSLCopyPeerTrust(self.0, &mut trust))?;\n            if trust.is_null() {\n                Ok(None)\n            } else {\n                Ok(Some(SecTrust::wrap_under_create_rule(trust)))\n            }\n        }\n    }\n\n    /// Returns the state of the session.\n    #[inline]\n    pub fn state(&self) -> Result<SessionState> {\n        unsafe {\n            let mut state = 0;\n            cvt(SSLGetSessionState(self.0, &mut state))?;\n            Ok(SessionState(state))\n        }\n    }\n\n    /// Returns the protocol version being used by the session.\n    #[inline]\n    pub fn negotiated_protocol_version(&self) -> Result<SslProtocol> {\n        unsafe {\n            let mut version = 0;\n            cvt(SSLGetNegotiatedProtocolVersion(self.0, &mut version))?;\n            Ok(SslProtocol(version))\n        }\n    }\n\n    /// Returns the maximum protocol version allowed by the session.\n    #[inline]\n    pub fn protocol_version_max(&self) -> Result<SslProtocol> {\n        unsafe {\n            let mut version = 0;\n            cvt(SSLGetProtocolVersionMax(self.0, &mut version))?;\n            Ok(SslProtocol(version))\n        }\n    }\n\n    /// Sets the maximum protocol version allowed by the session.\n    #[inline]\n    pub fn set_protocol_version_max(&mut self, max_version: SslProtocol) -> Result<()> {\n        unsafe { cvt(SSLSetProtocolVersionMax(self.0, max_version.0)) }\n    }\n\n    /// Returns the minimum protocol version allowed by the session.\n    #[inline]\n    pub fn protocol_version_min(&self) -> Result<SslProtocol> {\n        unsafe {\n            let mut version = 0;\n            cvt(SSLGetProtocolVersionMin(self.0, &mut version))?;\n            Ok(SslProtocol(version))\n        }\n    }\n\n    /// Sets the minimum protocol version allowed by the session.\n    #[inline]\n    pub fn set_protocol_version_min(&mut self, min_version: SslProtocol) -> Result<()> {\n        unsafe { cvt(SSLSetProtocolVersionMin(self.0, min_version.0)) }\n    }\n\n    /// Returns the set of protocols selected via ALPN if it succeeded.\n    pub fn alpn_protocols(&self) -> Result<Vec<String>> {\n        let mut array: CFArrayRef = ptr::null();\n        unsafe {\n            cvt(SSLCopyALPNProtocols(self.0, &mut array))?;\n\n            if array.is_null() {\n                return Ok(vec![]);\n            }\n\n            let array = CFArray::<CFString>::wrap_under_create_rule(array);\n            Ok(array.into_iter().map(|p| p.to_string()).collect())\n        }\n    }\n\n    /// Configures the set of protocols use for ALPN.\n    ///\n    /// This is only used for client-side connections.\n    pub fn set_alpn_protocols(&mut self, protocols: &[impl AsRef<str>]) -> Result<()> {\n        // When CFMutableArray is added to core-foundation and IntoIterator trait\n        // is implemented for CFMutableArray, the code below should directly collect\n        // into a CFMutableArray.\n        let protocols = CFArray::from_CFTypes(\n            &protocols\n                .iter()\n                .map(|proto| CFString::new(proto.as_ref()))\n                .collect::<Vec<_>>(),\n        );\n\n        unsafe { cvt(SSLSetALPNProtocols(self.0, protocols.as_concrete_TypeRef())) }\n    }\n\n    /// Sets whether the client sends the `SessionTicket` extension in its `ClientHello`.\n    ///\n    /// On its own, this will just cause the client to send an empty `SessionTicket` extension on\n    /// every connection. [`SslContext::set_peer_id`] must also be used to key the session\n    /// ticket returned by the server.\n    ///\n    /// [`SslContext::set_peer_id`]: #method.set_peer_id\n    pub fn set_session_tickets_enabled(&mut self, enabled: bool) -> Result<()> {\n        unsafe { cvt(SSLSetSessionTicketsEnabled(self.0, Boolean::from(enabled))) }\n    }\n\n    /// Returns the number of bytes which can be read without triggering a\n    /// `read` call in the underlying stream.\n    #[inline]\n    pub fn buffered_read_size(&self) -> Result<usize> {\n        unsafe {\n            let mut size = 0;\n            cvt(SSLGetBufferedReadSize(self.0, &mut size))?;\n            Ok(size)\n        }\n    }\n\n    impl_options! {\n        /// If enabled, the handshake process will pause and return instead of\n        /// automatically validating a server's certificate.\n        const kSSLSessionOptionBreakOnServerAuth: break_on_server_auth & set_break_on_server_auth,\n        /// If enabled, the handshake process will pause and return after\n        /// the server requests a certificate from the client.\n        const kSSLSessionOptionBreakOnCertRequested: break_on_cert_requested & set_break_on_cert_requested,\n        /// If enabled, the handshake process will pause and return instead of\n        /// automatically validating a client's certificate.\n        const kSSLSessionOptionBreakOnClientAuth: break_on_client_auth & set_break_on_client_auth,\n        /// If enabled, TLS false start will be performed if an appropriate\n        /// cipher suite is negotiated.\n        ///\n        const kSSLSessionOptionFalseStart: false_start & set_false_start,\n        /// If enabled, 1/n-1 record splitting will be enabled for TLS 1.0\n        /// connections using block ciphers to mitigate the BEAST attack.\n        ///\n        const kSSLSessionOptionSendOneByteRecord: send_one_byte_record & set_send_one_byte_record,\n    }\n\n    fn into_stream<S>(self, stream: S) -> Result<SslStream<S>>\n    where S: Read + Write {\n        unsafe {\n            let ret = SSLSetIOFuncs(self.0, read_func::<S>, write_func::<S>);\n            if ret != errSecSuccess {\n                return Err(Error::from_code(ret));\n            }\n\n            let stream = Connection { stream, err: None, panic: None };\n            let stream = Box::into_raw(Box::new(stream));\n            let ret = SSLSetConnection(self.0, stream.cast());\n            if ret != errSecSuccess {\n                let _conn = Box::from_raw(stream);\n                return Err(Error::from_code(ret));\n            }\n\n            Ok(SslStream { ctx: self, _m: PhantomData })\n        }\n    }\n\n    /// Performs the SSL/TLS handshake.\n    pub fn handshake<S>(self, stream: S) -> result::Result<SslStream<S>, HandshakeError<S>>\n    where\n        S: Read + Write,\n    {\n        self.into_stream(stream)\n            .map_err(HandshakeError::Failure)\n            .and_then(SslStream::handshake)\n    }\n}\n\nstruct Connection<S> {\n    stream: S,\n    err: Option<io::Error>,\n    panic: Option<Box<dyn Any + Send>>,\n}\n\n// the logic here is based off of libcurl's\n#[cold]\nfn translate_err(e: &io::Error) -> OSStatus {\n    match e.kind() {\n        io::ErrorKind::NotFound => errSSLClosedGraceful,\n        io::ErrorKind::ConnectionReset => errSSLClosedAbort,\n        io::ErrorKind::WouldBlock |\n        io::ErrorKind::NotConnected => errSSLWouldBlock,\n        _ => errSecIO,\n    }\n}\n\nunsafe extern \"C\" fn read_func<S>(\n    connection: SSLConnectionRef,\n    data: *mut c_void,\n    data_length: *mut usize,\n) -> OSStatus\nwhere S: Read {\n    if data.is_null() || data_length.is_null() || connection.is_null() {\n        return errSecParam;\n    }\n\n    let conn: &mut Connection<S> = unsafe { &mut *(connection as *mut _) };\n    let data = unsafe { slice::from_raw_parts_mut(data.cast::<u8>(), *data_length) };\n    let mut read = 0;\n\n    let ret = panic::catch_unwind(AssertUnwindSafe(|| {\n        let mut data = data;\n        while !data.is_empty() {\n            match conn.stream.read(data) {\n                Ok(0) => return errSSLClosedNoNotify,\n                Ok(len) => {\n                    let Some(rest) = data.get_mut(len..) else {\n                        return errSecIO;\n                    };\n                    data = rest;\n                    read += len;\n                },\n                Err(e) => {\n                    let ret = translate_err(&e);\n                    conn.err = Some(e);\n                    return ret;\n                },\n            }\n        }\n        errSecSuccess\n    }))\n    .unwrap_or_else(|e| {\n        conn.panic = Some(e);\n        errSecIO\n    });\n\n    unsafe {\n        *data_length = read;\n    }\n    ret\n}\n\nunsafe extern \"C\" fn write_func<S>(\n    connection: SSLConnectionRef,\n    data: *const c_void,\n    data_length: *mut usize,\n) -> OSStatus\nwhere S: Write {\n    if data.is_null() || data_length.is_null() || connection.is_null() {\n        return errSecParam;\n    }\n\n    let conn: &mut Connection<S> = unsafe { &mut *(connection as *mut _) };\n    let mut written = 0;\n    let mut data = unsafe {\n        slice::from_raw_parts(data.cast::<u8>(), *data_length)\n    };\n\n    let ret = panic::catch_unwind(AssertUnwindSafe(|| {\n        while !data.is_empty() {\n            match conn.stream.write(data) {\n                Ok(0) => return errSSLClosedNoNotify,\n                Ok(len) => {\n                    let Some(rest) = data.get(len..) else {\n                        return errSecIO;\n                    };\n                    data = rest;\n                    written += len;\n                },\n                Err(e) => {\n                    let ret = translate_err(&e);\n                    conn.err = Some(e);\n                    return ret;\n                },\n            }\n        }\n        // Need to flush during the handshake so that the handshake doesn't stall on buffered\n        // write streams. It would be better if we only flushed automatically during the\n        // handshake, and not for the remainder of the stream.\n        if let Err(e) = conn.stream.flush() {\n            let ret = translate_err(&e);\n            conn.err = Some(e);\n            return ret;\n        }\n        errSecSuccess\n    }))\n    .unwrap_or_else(|e| {\n        conn.panic = Some(e);\n        errSecIO\n    });\n\n    unsafe { *data_length = written };\n    ret\n}\n\n/// A type implementing SSL/TLS encryption over an underlying stream.\npub struct SslStream<S> {\n    ctx: SslContext,\n    _m: PhantomData<S>,\n}\n\nimpl<S: fmt::Debug> fmt::Debug for SslStream<S> {\n    #[cold]\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt.debug_struct(\"SslStream\")\n            .field(\"context\", &self.ctx)\n            .field(\"stream\", self.get_ref())\n            .finish()\n    }\n}\n\nimpl<S> Drop for SslStream<S> {\n    fn drop(&mut self) {\n        unsafe {\n            let mut conn = ptr::null();\n            let ret = SSLGetConnection(self.ctx.0, &mut conn);\n            assert!(ret == errSecSuccess);\n            let _ = Box::<Connection<S>>::from_raw(conn as *mut _);\n        }\n    }\n}\n\nimpl<S> SslStream<S> {\n    fn handshake(mut self) -> result::Result<Self, HandshakeError<S>> {\n        match unsafe { SSLHandshake(self.ctx.0) } {\n            errSecSuccess => Ok(self),\n            reason @ (errSSLPeerAuthCompleted\n            | errSSLClientCertRequested\n            | errSSLWouldBlock\n            | errSSLClientHelloReceived) => {\n                Err(HandshakeError::Interrupted(MidHandshakeSslStream {\n                    stream: self,\n                    error: Error::from_code(reason),\n                }))\n            },\n            err => {\n                self.check_panic();\n                Err(HandshakeError::Failure(Error::from_code(err)))\n            },\n        }\n    }\n\n    /// Returns a shared reference to the inner stream.\n    #[inline(always)]\n    #[must_use]\n    pub fn get_ref(&self) -> &S {\n        &self.connection().stream\n    }\n\n    /// Returns a mutable reference to the underlying stream.\n    #[inline(always)]\n    pub fn get_mut(&mut self) -> &mut S {\n        &mut self.connection_mut().stream\n    }\n\n    /// Returns a shared reference to the `SslContext` of the stream.\n    #[inline(always)]\n    #[must_use]\n    pub fn context(&self) -> &SslContext {\n        &self.ctx\n    }\n\n    /// Returns a mutable reference to the `SslContext` of the stream.\n    #[inline(always)]\n    pub fn context_mut(&mut self) -> &mut SslContext {\n        &mut self.ctx\n    }\n\n    /// Shuts down the connection.\n    pub fn close(&mut self) -> result::Result<(), io::Error> {\n        unsafe {\n            let ret = SSLClose(self.ctx.0);\n            if ret == errSecSuccess {\n                Ok(())\n            } else {\n                Err(self.get_error(ret))\n            }\n        }\n    }\n\n    fn connection(&self) -> &Connection<S> {\n        unsafe {\n            let mut conn = ptr::null();\n            let ret = SSLGetConnection(self.ctx.0, &mut conn);\n            assert!(ret == errSecSuccess);\n\n            &mut *(conn as *mut Connection<S>)\n        }\n    }\n\n    fn connection_mut(&mut self) -> &mut Connection<S> {\n        unsafe {\n            let mut conn = ptr::null();\n            let ret = SSLGetConnection(self.ctx.0, &mut conn);\n            assert!(ret == errSecSuccess);\n\n            &mut *(conn as *mut Connection<S>)\n        }\n    }\n\n    #[cold]\n    fn check_panic(&mut self) {\n        let conn = self.connection_mut();\n        if let Some(err) = conn.panic.take() {\n            panic::resume_unwind(err);\n        }\n    }\n\n    #[cold]\n    fn get_error(&mut self, ret: OSStatus) -> io::Error {\n        self.check_panic();\n\n        if let Some(err) = self.connection_mut().err.take() {\n            err\n        } else {\n            io::Error::new(io::ErrorKind::Other, Error::from_code(ret))\n        }\n    }\n}\n\nimpl<S: Read + Write> Read for SslStream<S> {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        // Below we base our return value off the amount of data read, so a\n        // zero-length buffer might cause us to erroneously interpret this\n        // request as an error. Instead short-circuit that logic and return\n        // `Ok(0)` instead.\n        if buf.is_empty() {\n            return Ok(0);\n        }\n\n        // If some data was buffered but not enough to fill `buf`, SSLRead\n        // will try to read a new packet. This is bad because there may be\n        // no more data but the socket is remaining open (e.g HTTPS with\n        // Connection: keep-alive).\n        let buffered = self.context().buffered_read_size().unwrap_or(0);\n        let to_read = if buffered > 0 {\n            cmp::min(buffered, buf.len())\n        } else {\n            buf.len()\n        };\n\n        unsafe {\n            let mut nread = 0;\n            let ret = SSLRead(self.ctx.0, buf.as_mut_ptr().cast(), to_read, &mut nread);\n            // SSLRead can return an error at the same time it returns the last\n            // chunk of data (!)\n            if nread > 0 {\n                return Ok(nread);\n            }\n\n            match ret {\n                errSSLClosedGraceful | errSSLClosedAbort | errSSLClosedNoNotify => Ok(0),\n                // this error isn't fatal\n                errSSLPeerAuthCompleted => self.read(buf),\n                _ => Err(self.get_error(ret)),\n            }\n        }\n    }\n}\n\nimpl<S: Read + Write> Write for SslStream<S> {\n    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {\n        // Like above in read, short circuit a 0-length write\n        if buf.is_empty() {\n            return Ok(0);\n        }\n        unsafe {\n            let mut nwritten = 0;\n            let ret = SSLWrite(\n                self.ctx.0,\n                buf.as_ptr().cast(),\n                buf.len(),\n                &mut nwritten,\n            );\n            // just to be safe, base success off of nwritten rather than ret\n            // for the same reason as in read\n            if nwritten > 0 {\n                Ok(nwritten)\n            } else {\n                Err(self.get_error(ret))\n            }\n        }\n    }\n\n    fn flush(&mut self) -> io::Result<()> {\n        self.connection_mut().stream.flush()\n    }\n}\n\n/// A builder type to simplify the creation of client side `SslStream`s.\n#[derive(Debug)]\npub struct ClientBuilder {\n    identity: Option<SecIdentity>,\n    certs: Vec<SecCertificate>,\n    chain: Vec<SecCertificate>,\n    protocol_min: Option<SslProtocol>,\n    protocol_max: Option<SslProtocol>,\n    trust_certs_only: bool,\n    use_sni: bool,\n    danger_accept_invalid_certs: bool,\n    danger_accept_invalid_hostnames: bool,\n    whitelisted_ciphers: Vec<CipherSuite>,\n    blacklisted_ciphers: Vec<CipherSuite>,\n    alpn: Option<Vec<Box<str>>>,\n    enable_session_tickets: bool,\n}\n\nimpl Default for ClientBuilder {\n    #[inline(always)]\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl ClientBuilder {\n    /// Creates a new builder with default options.\n    #[inline]\n    #[must_use]\n    pub fn new() -> Self {\n        Self {\n            identity: None,\n            certs: Vec::new(),\n            chain: Vec::new(),\n            protocol_min: None,\n            protocol_max: None,\n            trust_certs_only: false,\n            use_sni: true,\n            danger_accept_invalid_certs: false,\n            danger_accept_invalid_hostnames: false,\n            whitelisted_ciphers: Vec::new(),\n            blacklisted_ciphers: Vec::new(),\n            alpn: None,\n            enable_session_tickets: false,\n        }\n    }\n\n    /// Specifies the set of root certificates to trust when\n    /// verifying the server's certificate.\n    #[inline]\n    pub fn anchor_certificates(&mut self, certs: &[SecCertificate]) -> &mut Self {\n        certs.clone_into(&mut self.certs);\n        self\n    }\n\n    /// Add the certificate the set of root certificates to trust\n    /// when verifying the server's certificate.\n    #[inline]\n    pub fn add_anchor_certificate(&mut self, certs: &SecCertificate) -> &mut Self {\n        self.certs.push(certs.to_owned());\n        self\n    }\n\n    /// Specifies whether to trust the built-in certificates in addition\n    /// to specified anchor certificates.\n    #[inline(always)]\n    pub fn trust_anchor_certificates_only(&mut self, only: bool) -> &mut Self {\n        self.trust_certs_only = only;\n        self\n    }\n\n    /// Specifies whether to trust invalid certificates.\n    ///\n    /// # Warning\n    ///\n    /// You should think very carefully before using this method. If invalid\n    /// certificates are trusted, *any* certificate for *any* site will be\n    /// trusted for use. This includes expired certificates. This introduces\n    /// significant vulnerabilities, and should only be used as a last resort.\n    #[inline(always)]\n    pub fn danger_accept_invalid_certs(&mut self, noverify: bool) -> &mut Self {\n        self.danger_accept_invalid_certs = noverify;\n        self\n    }\n\n    /// Specifies whether to use Server Name Indication (SNI).\n    #[inline(always)]\n    pub fn use_sni(&mut self, use_sni: bool) -> &mut Self {\n        self.use_sni = use_sni;\n        self\n    }\n\n    /// Specifies whether to verify that the server's hostname matches its certificate.\n    ///\n    /// # Warning\n    ///\n    /// You should think very carefully before using this method. If hostnames are not verified,\n    /// *any* valid certificate for *any* site will be trusted for use. This introduces significant\n    /// vulnerabilities, and should only be used as a last resort.\n    #[inline(always)]\n    pub fn danger_accept_invalid_hostnames(\n        &mut self,\n        danger_accept_invalid_hostnames: bool,\n    ) -> &mut Self {\n        self.danger_accept_invalid_hostnames = danger_accept_invalid_hostnames;\n        self\n    }\n\n    /// Set a whitelist of enabled ciphers. Any ciphers not whitelisted will be disabled.\n    pub fn whitelist_ciphers(&mut self, whitelisted_ciphers: &[CipherSuite]) -> &mut Self {\n        whitelisted_ciphers.clone_into(&mut self.whitelisted_ciphers);\n        self\n    }\n\n    /// Set a blacklist of disabled ciphers. Blacklisted ciphers will be disabled.\n    pub fn blacklist_ciphers(&mut self, blacklisted_ciphers: &[CipherSuite]) -> &mut Self {\n        blacklisted_ciphers.clone_into(&mut self.blacklisted_ciphers);\n        self\n    }\n\n    /// Use the specified identity as a SSL/TLS client certificate.\n    pub fn identity(&mut self, identity: &SecIdentity, chain: &[SecCertificate]) -> &mut Self {\n        self.identity = Some(identity.clone());\n        chain.clone_into(&mut self.chain);\n        self\n    }\n\n    /// Configure the minimum protocol that this client will support.\n    #[inline(always)]\n    pub fn protocol_min(&mut self, min: SslProtocol) -> &mut Self {\n        self.protocol_min = Some(min);\n        self\n    }\n\n    /// Configure the minimum protocol that this client will support.\n    #[inline(always)]\n    pub fn protocol_max(&mut self, max: SslProtocol) -> &mut Self {\n        self.protocol_max = Some(max);\n        self\n    }\n\n    /// Configures the set of protocols used for ALPN.\n    pub fn alpn_protocols(&mut self, protocols: &[&str]) -> &mut Self {\n        self.alpn = Some(protocols.iter().copied().map(Box::from).collect());\n        self\n    }\n\n    /// Configures the use of the RFC 5077 `SessionTicket` extension.\n    ///\n    /// Defaults to `false`.\n    #[inline(always)]\n    pub fn enable_session_tickets(&mut self, enable: bool) -> &mut Self {\n        self.enable_session_tickets = enable;\n        self\n    }\n\n    /// Initiates a new SSL/TLS session over a stream connected to the specified domain.\n    ///\n    /// If both SNI and hostname verification are disabled, the value of `domain` will be ignored.\n    pub fn handshake<S>(\n        &self,\n        domain: &str,\n        stream: S,\n    ) -> result::Result<SslStream<S>, ClientHandshakeError<S>>\n    where\n        S: Read + Write,\n    {\n        // the logic for trust validation is in MidHandshakeClientBuilder::connect, so run all\n        // of the handshake logic through that.\n        let stream = MidHandshakeSslStream {\n            stream: self.ctx_into_stream(domain, stream)?,\n            error: Error::from(errSecSuccess),\n        };\n\n        let certs = self.certs.clone();\n        let stream = MidHandshakeClientBuilder {\n            stream,\n            domain: if self.danger_accept_invalid_hostnames {\n                None\n            } else {\n                Some(domain.to_string())\n            },\n            certs,\n            trust_certs_only: self.trust_certs_only,\n            danger_accept_invalid_certs: self.danger_accept_invalid_certs,\n        };\n        stream.handshake()\n    }\n\n    fn ctx_into_stream<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>>\n    where S: Read + Write {\n        let mut ctx = SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM)?;\n\n        if self.use_sni {\n            ctx.set_peer_domain_name(domain)?;\n        }\n        if let Some(identity) = &self.identity {\n            ctx.set_certificate(identity, &self.chain)?;\n        }\n        if let Some(alpn) = &self.alpn {\n            ctx.set_alpn_protocols(alpn)?;\n        }\n        if self.enable_session_tickets {\n            // We must use the domain here to ensure that we go through certificate validation\n            // again rather than resuming the session if the domain changes.\n            ctx.set_peer_id(domain.as_bytes())?;\n            ctx.set_session_tickets_enabled(true)?;\n        }\n        ctx.set_break_on_server_auth(true)?;\n        self.configure_protocols(&mut ctx)?;\n        self.configure_ciphers(&mut ctx)?;\n\n        ctx.into_stream(stream)\n    }\n\n    fn configure_protocols(&self, ctx: &mut SslContext) -> Result<()> {\n        if let Some(min) = self.protocol_min {\n            ctx.set_protocol_version_min(min)?;\n        }\n        if let Some(max) = self.protocol_max {\n            ctx.set_protocol_version_max(max)?;\n        }\n        Ok(())\n    }\n\n    fn configure_ciphers(&self, ctx: &mut SslContext) -> Result<()> {\n        let mut ciphers = if self.whitelisted_ciphers.is_empty() {\n            ctx.enabled_ciphers()?\n        } else {\n            self.whitelisted_ciphers.clone()\n        };\n\n        if !self.blacklisted_ciphers.is_empty() {\n            ciphers.retain(|cipher| !self.blacklisted_ciphers.contains(cipher));\n        }\n\n        ctx.set_enabled_ciphers(&ciphers)?;\n        Ok(())\n    }\n}\n\n/// A builder type to simplify the creation of server-side `SslStream`s.\n#[derive(Debug)]\npub struct ServerBuilder {\n    identity: SecIdentity,\n    certs: Vec<SecCertificate>,\n}\n\nimpl ServerBuilder {\n    /// Creates a new `ServerBuilder` which will use the specified identity\n    /// and certificate chain for handshakes.\n    #[must_use]\n    pub fn new(identity: &SecIdentity, certs: &[SecCertificate]) -> Self {\n        Self {\n            identity: identity.clone(),\n            certs: certs.to_owned(),\n        }\n    }\n\n    /// Creates a new `ServerBuilder` which will use the identity\n    /// from the given PKCS #12 data.\n    ///\n    /// This operation fails if PKCS #12 file contains zero or more than one identity.\n    ///\n    /// This is a shortcut for the most common operation.\n    pub fn from_pkcs12(pkcs12_der: &[u8], passphrase: &str) -> Result<Self> {\n        let mut identities: Vec<(SecIdentity, Vec<SecCertificate>)> = Pkcs12ImportOptions::new()\n            .passphrase(passphrase)\n            .import(pkcs12_der)?\n            .into_iter()\n            .filter_map(|idendity| {\n                Some((idendity.identity?, idendity.cert_chain.unwrap_or_default()))\n            })\n            .take(2)\n            .collect();\n        if identities.len() == 1 {\n            let (identity, certs) = identities.pop().unwrap();\n            Ok(Self { identity, certs })\n        } else {\n            // This error code is not really helpful\n            Err(Error::from_code(errSecParam))\n        }\n    }\n\n    /// Create a SSL context for lower-level stream initialization.\n    pub fn new_ssl_context(&self) -> Result<SslContext> {\n        let mut ctx = SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM)?;\n        ctx.set_certificate(&self.identity, &self.certs)?;\n        Ok(ctx)\n    }\n\n    /// Initiates a new SSL/TLS session over a stream.\n    pub fn handshake<S>(&self, stream: S) -> Result<SslStream<S>>\n    where S: Read + Write {\n        match self.new_ssl_context()?.handshake(stream) {\n            Ok(stream) => Ok(stream),\n            Err(HandshakeError::Interrupted(stream)) => Err(*stream.error()),\n            Err(HandshakeError::Failure(err)) => Err(err),\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use std::io::prelude::*;\n    use std::net::TcpStream;\n\n    use super::*;\n\n    #[test]\n    fn server_builder_from_pkcs12() {\n        let pkcs12_der = include_bytes!(\"../test/server.p12\");\n        ServerBuilder::from_pkcs12(pkcs12_der, \"password123\").unwrap();\n    }\n\n    #[test]\n    fn connect() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        p!(ctx.handshake(stream));\n    }\n\n    #[test]\n    fn connect_bad_domain() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"foobar.com\"));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        ctx.handshake(stream).expect_err(\"expected failure\");\n    }\n\n    #[test]\n    fn connect_buffered_stream() {\n        use std::io::BufWriter;\n\n        /// Small wrapper around a `TcpStream` to provide buffered writes.\n        #[derive(Debug)]\n        struct BufferedTcpStream {\n            reader: TcpStream,\n            writer: BufWriter<TcpStream>,\n        }\n\n        impl BufferedTcpStream {\n            fn new(tcp: TcpStream) -> std::io::Result<Self> {\n                Ok(Self {\n                    writer: BufWriter::with_capacity(500, tcp.try_clone()?),\n                    reader: tcp,\n                })\n            }\n        }\n\n        impl Read for BufferedTcpStream {\n            fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {\n                self.reader.read(buf)\n            }\n        }\n\n        impl Write for BufferedTcpStream {\n            fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {\n                self.writer.write(buf)\n            }\n\n            fn flush(&mut self) -> std::io::Result<()> {\n                self.writer.flush()\n            }\n        }\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let stream = p!(BufferedTcpStream::new(stream));\n        p!(ctx.handshake(stream));\n    }\n\n    #[test]\n    fn load_page() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let mut stream = p!(ctx.handshake(stream));\n        p!(stream.write_all(b\"GET / HTTP/1.0\\r\\n\\r\\n\"));\n        p!(stream.flush());\n        let mut buf = vec![];\n        p!(stream.read_to_end(&mut buf));\n        println!(\"{}\", String::from_utf8_lossy(&buf));\n    }\n\n    #[test]\n    fn client_no_session_ticket_resumption() {\n        for _ in 0..2 {\n            let stream = p!(TcpStream::connect(\"google.com:443\"));\n\n            // Manually handshake here.\n            let stream = MidHandshakeSslStream {\n                stream: ClientBuilder::new()\n                    .ctx_into_stream(\"google.com\", stream)\n                    .unwrap(),\n                error: Error::from(errSecSuccess),\n            };\n\n            let mut result = stream.handshake();\n\n            if let Err(HandshakeError::Interrupted(stream)) = result {\n                assert!(stream.server_auth_completed());\n                result = stream.handshake();\n            } else {\n                panic!(\"Unexpectedly skipped server auth\");\n            }\n\n            assert!(result.is_ok());\n        }\n    }\n\n    #[test]\n    fn client_session_ticket_resumption() {\n        // The first time through this loop, we should do a full handshake. The second time, we\n        // should immediately finish the handshake without breaking on server auth.\n        for i in 0..2 {\n            let stream = p!(TcpStream::connect(\"google.com:443\"));\n            let mut builder = ClientBuilder::new();\n            builder.enable_session_tickets(true);\n\n            // Manually handshake here.\n            let stream = MidHandshakeSslStream {\n                stream: builder.ctx_into_stream(\"google.com\", stream).unwrap(),\n                error: Error::from(errSecSuccess),\n            };\n\n            let mut result = stream.handshake();\n\n            if let Err(HandshakeError::Interrupted(stream)) = result {\n                assert!(stream.server_auth_completed());\n                assert_eq!(i, 0, \"Session ticket resumption did not work, server auth was not skipped\");\n                result = stream.handshake();\n            } else {\n                assert_eq!(i, 1, \"Unexpectedly skipped server auth\");\n            }\n\n            assert!(result.is_ok());\n        }\n    }\n\n    #[test]\n    fn client_alpn_accept() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        p!(ctx.set_alpn_protocols(&[\"h2\"]));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let stream = ctx.handshake(stream).unwrap();\n        assert_eq!(vec![\"h2\"], stream.context().alpn_protocols().unwrap());\n    }\n\n    #[test]\n    fn client_alpn_reject() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        p!(ctx.set_alpn_protocols(&[\"h2c\"]));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let stream = ctx.handshake(stream).unwrap();\n        assert!(stream.context().alpn_protocols().is_err());\n    }\n\n    #[test]\n    fn client_no_anchor_certs() {\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        assert!(ClientBuilder::new()\n            .trust_anchor_certificates_only(true)\n            .handshake(\"google.com\", stream)\n            .is_err());\n    }\n\n    #[test]\n    fn client_bad_domain() {\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        assert!(ClientBuilder::new()\n            .handshake(\"foobar.com\", stream)\n            .is_err());\n    }\n\n    #[test]\n    fn client_bad_domain_ignored() {\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        ClientBuilder::new()\n            .danger_accept_invalid_hostnames(true)\n            .handshake(\"foobar.com\", stream)\n            .unwrap();\n    }\n\n    #[test]\n    fn connect_no_verify_ssl() {\n        let stream = p!(TcpStream::connect(\"expired.badssl.com:443\"));\n        let mut builder = ClientBuilder::new();\n        builder.danger_accept_invalid_certs(true);\n        builder.handshake(\"expired.badssl.com\", stream).unwrap();\n    }\n\n    #[test]\n    fn load_page_client() {\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let mut stream = p!(ClientBuilder::new().handshake(\"google.com\", stream));\n        p!(stream.write_all(b\"GET / HTTP/1.0\\r\\n\\r\\n\"));\n        p!(stream.flush());\n        let mut buf = vec![];\n        p!(stream.read_to_end(&mut buf));\n        println!(\"{}\", String::from_utf8_lossy(&buf));\n    }\n\n    #[test]\n    #[cfg_attr(any(target_os = \"ios\", target_os = \"tvos\", target_os = \"watchos\", target_os = \"visionos\"), ignore)] // FIXME what's going on with ios?\n    fn cipher_configuration() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n        let ciphers = p!(ctx.enabled_ciphers());\n        let ciphers = ciphers\n            .iter()\n            .enumerate()\n            .filter_map(|(i, c)| if i % 2 == 0 { Some(*c) } else { None })\n            .collect::<Vec<_>>();\n        p!(ctx.set_enabled_ciphers(&ciphers));\n        assert_eq!(ciphers, p!(ctx.enabled_ciphers()));\n    }\n\n    #[test]\n    fn test_builder_whitelist_ciphers() {\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n\n        let ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        assert!(p!(ctx.enabled_ciphers()).len() > 1);\n\n        let ciphers = p!(ctx.enabled_ciphers());\n        let cipher = ciphers.first().unwrap();\n        let stream = p!(ClientBuilder::new()\n            .whitelist_ciphers(&[*cipher])\n            .ctx_into_stream(\"google.com\", stream));\n\n        assert_eq!(1, p!(stream.context().enabled_ciphers()).len());\n    }\n\n    #[test]\n    #[cfg_attr(any(target_os = \"ios\", target_os = \"tvos\", target_os = \"watchos\", target_os = \"visionos\"), ignore)] // FIXME same issue as cipher_configuration\n    fn test_builder_blacklist_ciphers() {\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n\n        let ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        let num = p!(ctx.enabled_ciphers()).len();\n        assert!(num > 1);\n\n        let ciphers = p!(ctx.enabled_ciphers());\n        let cipher = ciphers.first().unwrap();\n        let stream = p!(ClientBuilder::new()\n            .blacklist_ciphers(&[*cipher])\n            .ctx_into_stream(\"google.com\", stream));\n\n        assert_eq!(num - 1, p!(stream.context().enabled_ciphers()).len());\n    }\n\n    #[test]\n    fn idle_context_peer_trust() {\n        let ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n        assert!(ctx.peer_trust2().is_err());\n    }\n\n    #[test]\n    fn peer_id() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::SERVER, SslConnectionType::STREAM));\n        assert!(p!(ctx.peer_id()).is_none());\n        p!(ctx.set_peer_id(b\"foobar\"));\n        assert_eq!(p!(ctx.peer_id()), Some(&b\"foobar\"[..]));\n    }\n\n    #[test]\n    fn peer_domain_name() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        assert_eq!(\"\", p!(ctx.peer_domain_name()));\n        p!(ctx.set_peer_domain_name(\"foobar.com\"));\n        assert_eq!(\"foobar.com\", p!(ctx.peer_domain_name()));\n    }\n\n    #[test]\n    #[should_panic(expected = \"blammo\")]\n    fn write_panic() {\n        struct ExplodingStream(TcpStream);\n\n        impl Read for ExplodingStream {\n            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n                self.0.read(buf)\n            }\n        }\n\n        impl Write for ExplodingStream {\n            fn write(&mut self, _: &[u8]) -> io::Result<usize> {\n                panic!(\"blammo\");\n            }\n\n            fn flush(&mut self) -> io::Result<()> {\n                self.0.flush()\n            }\n        }\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let _ = ctx.handshake(ExplodingStream(stream));\n    }\n\n    #[test]\n    #[should_panic(expected = \"blammo\")]\n    fn read_panic() {\n        struct ExplodingStream(TcpStream);\n\n        impl Read for ExplodingStream {\n            fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {\n                panic!(\"blammo\");\n            }\n        }\n\n        impl Write for ExplodingStream {\n            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {\n                self.0.write(buf)\n            }\n\n            fn flush(&mut self) -> io::Result<()> {\n                self.0.flush()\n            }\n        }\n\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let _ = ctx.handshake(ExplodingStream(stream));\n    }\n\n    #[test]\n    fn zero_length_buffers() {\n        let mut ctx = p!(SslContext::new(SslProtocolSide::CLIENT, SslConnectionType::STREAM));\n        p!(ctx.set_peer_domain_name(\"google.com\"));\n        let stream = p!(TcpStream::connect(\"google.com:443\"));\n        let mut stream = ctx.handshake(stream).unwrap();\n        assert_eq!(stream.write(b\"\").unwrap(), 0);\n        assert_eq!(stream.read(&mut []).unwrap(), 0);\n    }\n}\n"
  },
  {
    "path": "security-framework/src/trust.rs",
    "content": "//! Trust evaluation support.\nuse core_foundation::array::CFArray;\n#[cfg(target_os = \"macos\")]\nuse core_foundation::array::CFArrayRef;\nuse core_foundation::base::TCFType;\nuse core_foundation::data::CFData;\nuse core_foundation::date::CFDate;\nuse core_foundation::{declare_TCFType, impl_TCFType};\nuse core_foundation_sys::base::{Boolean, CFIndex};\n\nuse security_framework_sys::trust::*;\nuse std::ptr;\n\nuse crate::base::Result;\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\nuse crate::key::SecKey;\nuse crate::policy::SecPolicy;\nuse core_foundation::error::{CFError, CFErrorRef};\n\n/// The result of trust evaluation.\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub struct TrustResult(SecTrustResultType);\n\nimpl TrustResult {\n    /// Indicates a denial by the user, do not proceed.\n    pub const DENY: Self = Self(kSecTrustResultDeny);\n    /// Indicates a trust policy failure that the user cannot override.\n    pub const FATAL_TRUST_FAILURE: Self = Self(kSecTrustResultFatalTrustFailure);\n    /// An invalid setting or result.\n    pub const INVALID: Self = Self(kSecTrustResultInvalid);\n    /// An error not related to trust validation.\n    pub const OTHER_ERROR: Self = Self(kSecTrustResultOtherError);\n    /// You may proceed.\n    pub const PROCEED: Self = Self(kSecTrustResultProceed);\n    /// Indicates a trust policy failure that the user can override.\n    pub const RECOVERABLE_TRUST_FAILURE: Self = Self(kSecTrustResultRecoverableTrustFailure);\n    /// The certificate is implicitly trusted.\n    pub const UNSPECIFIED: Self = Self(kSecTrustResultUnspecified);\n}\n\nimpl TrustResult {\n    /// Returns true if the result is \"successful\" - specifically `PROCEED` or `UNSPECIFIED`.\n    #[inline]\n    #[must_use]\n    pub fn success(self) -> bool {\n        matches!(self, Self::PROCEED | Self::UNSPECIFIED)\n    }\n}\n\ndeclare_TCFType! {\n    /// A type representing a trust evaluation for a certificate.\n    SecTrust, SecTrustRef\n}\nimpl_TCFType!(SecTrust, SecTrustRef, SecTrustGetTypeID);\n\nunsafe impl Sync for SecTrust {}\nunsafe impl Send for SecTrust {}\n\n#[cfg(target_os = \"macos\")]\nbitflags::bitflags! {\n    /// The option flags used to configure the evaluation of a `SecTrust`.\n    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\n    pub struct TrustOptions: SecTrustOptionFlags {\n        /// Allow expired certificates (except for the root certificate).\n        const ALLOW_EXPIRED = kSecTrustOptionAllowExpired;\n        /// Allow CA certificates as leaf certificates.\n        const LEAF_IS_CA = kSecTrustOptionLeafIsCA;\n        /// Allow network downloads of CA certificates.\n        const FETCH_ISSUER_FROM_NET = kSecTrustOptionFetchIssuerFromNet;\n        /// Allow expired root certificates.\n        const ALLOW_EXPIRED_ROOT = kSecTrustOptionAllowExpiredRoot;\n        /// Require a positive revocation check for each certificate.\n        const REQUIRE_REVOCATION_PER_CERT =  kSecTrustOptionRequireRevPerCert;\n        /// Use TrustSettings instead of anchors.\n        const USE_TRUST_SETTINGS = kSecTrustOptionUseTrustSettings;\n        /// Treat properly self-signed certificates as anchors implicitly.\n        const IMPLICIT_ANCHORS =  kSecTrustOptionImplicitAnchors;\n    }\n}\n\nimpl SecTrust {\n    /// Creates a `SecTrustRef` that is configured with a certificate chain, for validating\n    /// that chain against a collection of policies.\n    pub fn create_with_certificates(\n        certs: &[SecCertificate],\n        policies: &[SecPolicy],\n    ) -> Result<Self> {\n        let cert_array = CFArray::from_CFTypes(certs);\n        let policy_array = CFArray::from_CFTypes(policies);\n        let mut trust = ptr::null_mut();\n        unsafe {\n            cvt(SecTrustCreateWithCertificates(\n                cert_array.as_CFTypeRef(),\n                policy_array.as_CFTypeRef(),\n                &mut trust,\n            ))?;\n            Ok(Self(trust))\n        }\n    }\n\n    /// Sets the date and time against which the certificates in this trust object\n    /// are verified.\n    #[inline]\n    pub fn set_trust_verify_date(&mut self, date: &CFDate) -> Result<()> {\n        unsafe { cvt(SecTrustSetVerifyDate(self.0, date.as_concrete_TypeRef())) }\n    }\n\n    /// Sets additional anchor certificates used to validate trust.\n    pub fn set_anchor_certificates(&mut self, certs: &[SecCertificate]) -> Result<()> {\n        let certs = CFArray::from_CFTypes(certs);\n\n        unsafe {\n            cvt(SecTrustSetAnchorCertificates(\n                self.0,\n                certs.as_concrete_TypeRef(),\n            ))\n        }\n    }\n\n    /// Retrieves the anchor (root) certificates stored by macOS\n    #[cfg(target_os = \"macos\")]\n    pub fn copy_anchor_certificates() -> Result<Vec<SecCertificate>> {\n        let mut array: CFArrayRef = ptr::null();\n\n        unsafe {\n            cvt(SecTrustCopyAnchorCertificates(&mut array))?;\n        }\n\n        if array.is_null() {\n            return Ok(vec![]);\n        }\n\n        let array = unsafe { CFArray::<SecCertificate>::wrap_under_create_rule(array) };\n        Ok(array.into_iter().map(|c| c.clone()).collect())\n    }\n\n    /// If set to `true`, only the certificates specified by\n    /// `set_anchor_certificates` will be trusted, but not globally trusted\n    /// certificates.\n    #[inline]\n    pub fn set_trust_anchor_certificates_only(&mut self, only: bool) -> Result<()> {\n        unsafe { cvt(SecTrustSetAnchorCertificatesOnly(self.0, Boolean::from(only))) }\n    }\n\n    /// Sets the policy used to evaluate trust.\n    #[inline]\n    pub fn set_policy(&mut self, policy: &SecPolicy) -> Result<()> {\n        unsafe { cvt(SecTrustSetPolicies(self.0, policy.as_CFTypeRef())) }\n    }\n\n    /// Sets option flags for customizing evaluation of a trust object.\n    #[cfg(target_os = \"macos\")]\n    #[inline]\n    pub fn set_options(&mut self, options: TrustOptions) -> Result<()> {\n        unsafe { cvt(SecTrustSetOptions(self.0, options.bits())) }\n    }\n\n    /// Indicates whether this trust object is permitted to\n    /// fetch missing intermediate certificates from the network.\n    pub fn get_network_fetch_allowed(&mut self) -> Result<bool> {\n        let mut allowed = 0;\n\n        unsafe { cvt(SecTrustGetNetworkFetchAllowed(self.0, &mut allowed))? };\n\n        Ok(allowed != 0)\n    }\n\n    /// Specifies whether this trust object is permitted to\n    /// fetch missing intermediate certificates from the network.\n    #[inline]\n    pub fn set_network_fetch_allowed(&mut self, allowed: bool) -> Result<()> {\n        unsafe { cvt(SecTrustSetNetworkFetchAllowed(self.0, u8::from(allowed))) }\n    }\n\n    /// Attaches Online Certificate Status Protocol (OSCP) response data\n    /// to this trust object.\n    pub fn set_trust_ocsp_response<I: Iterator<Item = impl AsRef<[u8]>>>(\n        &mut self,\n        ocsp_response: I,\n    ) -> Result<()> {\n        let response: Vec<CFData> = ocsp_response\n            .into_iter()\n            .map(|bytes| CFData::from_buffer(bytes.as_ref()))\n            .collect();\n\n        let response = CFArray::from_CFTypes(&response);\n\n        unsafe { cvt(SecTrustSetOCSPResponse(self.0, response.as_CFTypeRef())) }\n    }\n\n    /// Attaches signed certificate timestamp data to this trust object.\n    pub fn set_signed_certificate_timestamps<I: Iterator<Item = impl AsRef<[u8]>>>(\n        &mut self,\n        scts: I,\n    ) -> Result<()> {\n        let scts: Vec<CFData> = scts\n            .into_iter()\n            .map(|bytes| CFData::from_buffer(bytes.as_ref()))\n            .collect();\n\n        let scts = CFArray::from_CFTypes(&scts);\n\n        unsafe { cvt(SecTrustSetSignedCertificateTimestamps(self.0, scts.as_concrete_TypeRef())) }\n    }\n\n    /// Returns the public key for a leaf certificate after it has been evaluated.\n    #[inline]\n    pub fn copy_public_key(&mut self) -> Result<SecKey> {\n        unsafe { Ok(SecKey::wrap_under_create_rule(SecTrustCopyPublicKey(self.0))) }\n    }\n\n    /// Evaluates trust.\n    #[deprecated(note = \"use evaluate_with_error\")]\n    pub fn evaluate(&self) -> Result<TrustResult> {\n        #[allow(deprecated)]\n        unsafe {\n            let mut result = kSecTrustResultInvalid;\n            cvt(SecTrustEvaluate(self.0, &mut result))?;\n            Ok(TrustResult(result))\n        }\n    }\n\n    /// Evaluates trust. Requires macOS 10.14 (checked at runtime) or iOS,\n    /// otherwise it just calls `evaluate()`.\n    pub fn evaluate_with_error(&self) -> Result<(), CFError> {\n        let mut error: CFErrorRef = ::std::ptr::null_mut();\n        let result = unsafe { SecTrustEvaluateWithError(self.0, &mut error) };\n        if !result {\n            assert!(!error.is_null());\n            // SAFETY: `SecTrustEvaluateWithError` expects us to release\n            // the error.\n            let error = unsafe { CFError::wrap_under_create_rule(error) };\n            return Err(error);\n        }\n        Ok(())\n    }\n\n    /// Gets the whole evaluated certificate chain.\n    ///\n    /// Note: evaluate must first be called on the `SecTrust`.\n    #[cfg(any(feature = \"macos-12\", not(target_os = \"macos\")))]\n    pub fn chain(&self) -> Vec<SecCertificate> {\n        let array = unsafe { SecTrustCopyCertificateChain(self.0) };\n\n        if array.is_null() {\n            return vec![];\n        }\n\n        let array = unsafe { CFArray::<SecCertificate>::wrap_under_create_rule(array) };\n        array.into_iter().map(|c| c.clone()).collect()\n    }\n\n    /// Returns the number of certificates in an evaluated certificate chain.\n    ///\n    /// Note: evaluate must first be called on the `SecTrust`.\n    #[inline(always)]\n    #[must_use]\n    #[deprecated(note = \"deprecated by Apple, use chain(), enable macos-12 feature\")]\n    // FIXME: this should have been usize. Don't expose CFIndex in Rust APIs.\n    pub fn certificate_count(&self) -> CFIndex {\n        unsafe { SecTrustGetCertificateCount(self.0) }\n    }\n\n    /// Returns a specific certificate from the certificate chain used to evaluate trust.\n    ///\n    /// Note: evaluate must first be called on the `SecTrust`.\n    #[deprecated(note = \"deprecated by Apple, use chain(), enable macos-12 feature\")]\n    #[must_use]\n    pub fn certificate_at_index(&self, ix: CFIndex) -> Option<SecCertificate> {\n        #[allow(deprecated)]\n        unsafe {\n            if self.certificate_count() <= ix {\n                None\n            } else {\n                let certificate = SecTrustGetCertificateAtIndex(self.0, ix);\n                Some(SecCertificate::wrap_under_get_rule(certificate.cast()))\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use crate::policy::SecPolicy;\n    use crate::secure_transport::SslProtocolSide;\n    use crate::test::certificate;\n    use crate::trust::SecTrust;\n\n    #[test]\n    #[allow(deprecated)]\n    fn create_with_certificates() {\n        let cert = certificate();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io\"));\n        let trust = SecTrust::create_with_certificates(&[cert], &[ssl_policy]).unwrap();\n        assert!(!trust.evaluate().unwrap().success());\n    }\n\n    #[test]\n    fn create_with_certificates_new() {\n        let cert = certificate();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io\"));\n        let trust = SecTrust::create_with_certificates(&[cert], &[ssl_policy]).unwrap();\n        assert!(trust.evaluate_with_error().is_err());\n    }\n\n    #[test]\n    #[allow(deprecated)]\n    fn certificate_count_and_at_index() {\n        let cert = certificate();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io\"));\n        let trust = SecTrust::create_with_certificates(&[cert], &[ssl_policy]).unwrap();\n        trust.evaluate().unwrap();\n\n        let count = trust.certificate_count();\n        // 1 (self-signed) or 2 (CA-signed, macOS builds chain)\n        assert!(count >= 1);\n\n        let cert_bytes = trust.certificate_at_index(0).unwrap().to_der();\n        assert_eq!(cert_bytes, certificate().to_der());\n    }\n\n    #[test]\n    #[allow(deprecated)]\n    fn certificate_count_and_at_index_new() {\n        let cert = certificate();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io\"));\n        let trust = SecTrust::create_with_certificates(&[cert], &[ssl_policy]).unwrap();\n        assert!(trust.evaluate_with_error().is_err());\n\n        let count = trust.certificate_count();\n        // 1 (self-signed) or 2 (CA-signed, macOS builds chain)\n        assert!(count >= 1);\n\n        let cert_bytes = trust.certificate_at_index(0).unwrap().to_der();\n        assert_eq!(cert_bytes, certificate().to_der());\n    }\n\n    #[test]\n    #[allow(deprecated)]\n    fn certificate_at_index_out_of_bounds() {\n        let cert = certificate();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io\"));\n\n        let trust = SecTrust::create_with_certificates(std::slice::from_ref(&cert), std::slice::from_ref(&ssl_policy)).unwrap();\n        trust.evaluate().unwrap();\n        assert!(trust.certificate_at_index(10).is_none());\n\n        let trust = SecTrust::create_with_certificates(&[cert], &[ssl_policy]).unwrap();\n        assert!(trust.evaluate_with_error().is_err());\n        assert!(trust.certificate_at_index(10).is_none());\n    }\n\n    #[test]\n    #[allow(deprecated)]\n    fn set_policy() {\n        let cert = certificate();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io.bogus\"));\n        let mut trust = SecTrust::create_with_certificates(&[cert], &[ssl_policy]).unwrap();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io\"));\n        trust.set_policy(&ssl_policy).unwrap();\n        assert!(!trust.evaluate().unwrap().success());\n    }\n\n    #[test]\n    fn set_policy_new() {\n        let cert = certificate();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io.bogus\"));\n        let mut trust = SecTrust::create_with_certificates(&[cert], &[ssl_policy]).unwrap();\n        let ssl_policy = SecPolicy::create_ssl(SslProtocolSide::CLIENT, Some(\"certifi.io\"));\n        trust.set_policy(&ssl_policy).unwrap();\n        assert!(trust.evaluate_with_error().is_err());\n    }\n}\n"
  },
  {
    "path": "security-framework/src/trust_settings.rs",
    "content": "//! Querying trust settings.\n\nuse core_foundation::array::{CFArray, CFArrayRef};\nuse core_foundation::base::{CFIndex, TCFType};\nuse core_foundation::dictionary::CFDictionary;\nuse core_foundation::number::CFNumber;\nuse core_foundation::string::CFString;\n\nuse core_foundation_sys::base::CFTypeRef;\nuse security_framework_sys::base::{errSecNoTrustSettings, errSecSuccess};\nuse security_framework_sys::trust_settings::*;\n\nuse std::ptr;\n\nuse crate::base::{Error, Result};\nuse crate::certificate::SecCertificate;\nuse crate::cvt;\n\n/// Which set of trust settings to query\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n#[repr(u32)]\npub enum Domain {\n    /// Per-user trust settings\n    User = kSecTrustSettingsDomainUser,\n    /// Locally administered, system-wide trust settings\n    Admin = kSecTrustSettingsDomainAdmin,\n    /// System trust settings\n    System = kSecTrustSettingsDomainSystem,\n}\n\nimpl From<Domain> for SecTrustSettingsDomain {\n    #[inline]\n    fn from(domain: Domain) -> Self {\n        match domain {\n            Domain::User => kSecTrustSettingsDomainUser,\n            Domain::Admin => kSecTrustSettingsDomainAdmin,\n            Domain::System => kSecTrustSettingsDomainSystem,\n        }\n    }\n}\n\n/// Trust settings for a specific certificate in a specific domain\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub enum TrustSettingsForCertificate {\n    /// Not used\n    Invalid,\n\n    /// This is a root certificate and is trusted, either explicitly or\n    /// implicitly.\n    TrustRoot,\n\n    /// This is a non-root certificate but is explicitly trusted.\n    TrustAsRoot,\n\n    /// Cert is explicitly distrusted.\n    Deny,\n\n    /// Neither trusted nor distrusted.\n    Unspecified,\n}\n\nimpl TrustSettingsForCertificate {\n    /// Create from `kSecTrustSettingsResult*` constant\n    fn new(value: i64) -> Self {\n        if value < 0 || value > i64::from(u32::MAX) {\n            return Self::Invalid;\n        }\n        match value as u32 {\n            kSecTrustSettingsResultTrustRoot => Self::TrustRoot,\n            kSecTrustSettingsResultTrustAsRoot => Self::TrustAsRoot,\n            kSecTrustSettingsResultDeny => Self::Deny,\n            kSecTrustSettingsResultUnspecified => Self::Unspecified,\n            _ => Self::Invalid,\n        }\n    }\n}\n\n/// Allows access to the certificates and their trust settings in a given domain.\npub struct TrustSettings {\n    domain: Domain,\n}\n\nimpl TrustSettings {\n    /// Create a new `TrustSettings` for the given domain.\n    ///\n    /// You can call `iter()` to discover the certificates with settings in this domain.\n    ///\n    /// Then you can call `tls_trust_settings_for_certificate()` with a given certificate\n    /// to learn what the aggregate trust setting for that certificate within this domain.\n    #[inline(always)]\n    #[must_use]\n    pub const fn new(domain: Domain) -> Self {\n        Self { domain }\n    }\n\n    /// Create an iterator over the certificates with settings in this domain.\n    /// This produces an empty iterator if there are no such certificates.\n    pub fn iter(&self) -> Result<TrustSettingsIter> {\n        let array = unsafe {\n            let mut array_ptr: CFArrayRef = ptr::null_mut();\n\n            // SecTrustSettingsCopyCertificates returns errSecNoTrustSettings\n            // if no items have trust settings in the given domain.  We map\n            // that to an empty TrustSettings iterator.\n            match SecTrustSettingsCopyCertificates(self.domain.into(), &mut array_ptr) {\n                errSecNoTrustSettings => CFArray::from_CFTypes(&[]),\n                errSecSuccess => CFArray::<SecCertificate>::wrap_under_create_rule(array_ptr),\n                err => return Err(Error::from_code(err)),\n            }\n        };\n\n        Ok(TrustSettingsIter { index: 0, array })\n    }\n\n    ///set trust settings to \"\"always trust this root certificate regardless of use.\".\n    /// Sets the trust settings for the provided certificate to \"always trust this root certificate\n    /// regardless of use.\"\n    ///\n    /// This method configures the trust settings for the specified certificate, indicating that it should\n    /// always be trusted as a TLS root certificate, regardless of its usage.\n    ///\n    /// If successful, the trust settings are updated for the certificate in the given domain. If the\n    /// certificate had no previous trust settings in the domain, new trust settings are created. If the\n    /// certificate had existing trust settings, they are replaced with the new settings.\n    ///\n    /// It is not possible to modify per-user trust settings when not running in a GUI\n    /// environment, if you try it will return error `2070: errSecInternalComponent`\n    #[cfg(target_os = \"macos\")]\n    pub fn set_trust_settings_always(&self, cert: &SecCertificate) -> Result<()> {\n        let domain = self.domain;\n        let trust_settings: CFTypeRef = ptr::null_mut();\n        cvt(unsafe {\n            SecTrustSettingsSetTrustSettings(\n                cert.as_concrete_TypeRef(),\n                domain.into(),\n                trust_settings,\n            )\n        })\n    }\n\n    /// Returns the aggregate trust setting for the given certificate.\n    ///\n    /// This tells you whether the certificate should be trusted as a TLS\n    /// root certificate.\n    ///\n    /// If the certificate has no trust settings in the given domain, the\n    /// `errSecItemNotFound` error is returned.\n    ///\n    /// If the certificate has no specific trust settings for TLS in the\n    /// given domain `None` is returned.\n    ///\n    /// Otherwise, the specific trust settings are aggregated and returned.\n    pub fn tls_trust_settings_for_certificate(&self, cert: &SecCertificate) -> Result<Option<TrustSettingsForCertificate>> {\n        let trust_settings = unsafe {\n            let mut array_ptr: CFArrayRef = ptr::null_mut();\n            let cert_ptr = cert.as_CFTypeRef() as *mut _;\n            cvt(SecTrustSettingsCopyTrustSettings(cert_ptr, self.domain.into(), &mut array_ptr))?;\n            CFArray::<CFDictionary>::wrap_under_create_rule(array_ptr)\n        };\n\n        for settings in trust_settings.iter() {\n            // Reject settings for non-SSL policies\n            let is_not_ssl_policy = {\n                let policy_name_key = CFString::from_static_string(\"kSecTrustSettingsPolicyName\");\n                let ssl_policy_name = CFString::from_static_string(\"sslServer\");\n\n                let maybe_name: Option<CFString> = settings\n                    .find(policy_name_key.as_CFTypeRef().cast())\n                    .map(|name| unsafe { CFString::wrap_under_get_rule((*name).cast()) });\n\n                matches!(maybe_name, Some(name) if name != ssl_policy_name)\n            };\n\n            if is_not_ssl_policy {\n                continue;\n            }\n\n            // Evaluate \"effective trust settings\" for this usage constraint.\n            let maybe_trust_result = {\n                let settings_result_key = CFString::from_static_string(\"kSecTrustSettingsResult\");\n                settings\n                    .find(settings_result_key.as_CFTypeRef().cast())\n                    .map(|num| unsafe { CFNumber::wrap_under_get_rule((*num).cast()) })\n                    .and_then(|num| num.to_i64())\n            };\n\n            // \"Note that an empty Trust Settings array means \"always trust this cert,\n            //  with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot\".\"\n            let trust_result = TrustSettingsForCertificate::new(maybe_trust_result\n                .unwrap_or_else(|| i64::from(kSecTrustSettingsResultTrustRoot)));\n\n            match trust_result {\n                TrustSettingsForCertificate::Unspecified |\n                TrustSettingsForCertificate::Invalid => { continue; },\n                _ => return Ok(Some(trust_result)),\n            }\n        }\n\n        // There were no more specific settings.  This might mean the certificate\n        // is to be trusted anyway (since, eg, it's in system store), but leave\n        // the caller to make this decision.\n        Ok(None)\n    }\n}\n\n/// Iterator over certificates.\npub struct TrustSettingsIter {\n    array: CFArray<SecCertificate>,\n    index: CFIndex,\n}\n\nimpl Iterator for TrustSettingsIter {\n    type Item = SecCertificate;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.index >= self.array.len() {\n            None\n        } else {\n            let cert = self.array.get(self.index).unwrap();\n            self.index += 1;\n            Some(cert.clone())\n        }\n    }\n\n    #[inline]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let left = (self.array.len() as usize).saturating_sub(self.index as usize);\n        (left, Some(left))\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use crate::test::certificate;\n\n    fn list_for_domain(domain: Domain) {\n        println!(\"--- domain: {domain:?}\");\n        let ts = TrustSettings::new(domain);\n        let iterator = ts.iter().unwrap();\n\n        for (i, cert) in iterator.enumerate() {\n            println!(\"cert({i:?}) = {cert:?}\");\n            println!(\"  settings = {:?}\", ts.tls_trust_settings_for_certificate(&cert));\n        }\n        println!(\"---\");\n    }\n\n    #[test]\n    fn list_for_user() {\n        list_for_domain(Domain::User);\n    }\n\n    #[test]\n    fn list_for_system() {\n        list_for_domain(Domain::System);\n    }\n\n    #[test]\n    fn list_for_admin() {\n        list_for_domain(Domain::Admin);\n    }\n\n    #[test]\n    fn test_system_certs_are_present() {\n        let system = TrustSettings::new(Domain::System).iter().unwrap().count();\n\n        // 168 at the time of writing\n        assert!(system > 100);\n    }\n\n    #[test]\n    fn test_isrg_root_exists_and_is_trusted() {\n        let ts = TrustSettings::new(Domain::System);\n        assert_eq!(\n            ts.iter()\n                .unwrap()\n                .find(|cert| cert.subject_summary() == \"ISRG Root X1\")\n                .and_then(|cert| ts.tls_trust_settings_for_certificate(&cert).unwrap()),\n            None\n        );\n        // ^ this is a case where None means \"always trust\", according to Apple docs:\n        //\n        // \"Note that an empty Trust Settings array means \"always trust this cert,\n        //  with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot\".\"\n    }\n\n    #[test]\n    fn test_unknown_cert_is_not_trusted() {\n        let ts = TrustSettings::new(Domain::System);\n        let cert = certificate();\n        assert_eq!(\n            ts.tls_trust_settings_for_certificate(&cert).err().unwrap().message(),\n            Some(\"The specified item could not be found in the keychain.\".into())\n        );\n    }\n}\n"
  },
  {
    "path": "security-framework/test/regen-certs.sh",
    "content": "#!/bin/bash\nset -xe\n\ncd \"$(dirname \"$0\")\"\nTEST_DIR=\"$(pwd)\"\n\nopenssl genrsa -out ca.key 2048\n\ncat > ca.cnf << 'EOF'\n[req]\ndistinguished_name = req_distinguished_name\nx509_extensions = v3_ca\nprompt = no\n\n[req_distinguished_name]\nC = US\nST = California\nL = Palo Alto\nO = Foobar LLC\nOU = Dev Land\nCN = foobar.com\n\n[v3_ca]\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid:always,issuer:always\nbasicConstraints = critical, CA:TRUE\nkeyUsage = critical, keyCertSign, cRLSign\nEOF\n\n# Use 825 days max (Apple's current limit for TLS certificates)\nopenssl req -new -x509 -key ca.key -out ca.crt -days 825 \\\n    -sha256 \\\n    -config ca.cnf\n\nopenssl genrsa -out server.key 2048\n\ncat > server_req.cnf << 'EOF'\n[req]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\nprompt = no\n\n[req_distinguished_name]\nC = US\nST = California\nL = Palo Alto\nO = Foobar LLC\nOU = Dev Land\nCN = foobar.com\n\n[v3_req]\nsubjectAltName = @alt_names\n\n[alt_names]\nDNS.1 = foobar.com\nDNS.2 = localhost\nIP.1 = 127.0.0.1\nEOF\n\nopenssl req -new -key server.key -out server.csr -config server_req.cnf\n\ncat > server_ext.cnf << 'EOF'\n[v3_req]\nbasicConstraints = CA:FALSE\nkeyUsage = critical, digitalSignature, keyEncipherment\nextendedKeyUsage = serverAuth\nsubjectKeyIdentifier = hash\nsubjectAltName = @alt_names\n\n[alt_names]\nDNS.1 = foobar.com\nDNS.2 = localhost\nIP.1 = 127.0.0.1\nEOF\n\nopenssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \\\n    -out server.crt -days 825 -sha256 \\\n    -extfile server_ext.cnf -extensions v3_req\n\nopenssl x509 -in ca.crt -out ca.der -outform DER\n\nopenssl x509 -in server.crt -out server.der -outform DER\n\nopenssl pkcs12 -export -out server.p12 -inkey server.key -in server.crt \\\n    -certfile ca.crt \\\n    -password pass:password123 \\\n    -certpbe PBE-SHA1-3DES \\\n    -keypbe PBE-SHA1-3DES \\\n    -macalg SHA1 \\\n    -legacy\n\nrm -f \"$TEST_DIR/server.keychain\"\n\nsecurity create-keychain -p password123 \"$TEST_DIR/server.keychain\"\n\nsecurity import server.p12 -k \"$TEST_DIR/server.keychain\" -P password123 -A\n\nsecurity set-keychain-settings \"$TEST_DIR/server.keychain\"\nsecurity unlock-keychain -p password123 \"$TEST_DIR/server.keychain\"\n\nrm -f ca.key ca.crt ca.srl server.crt server.csr ca.cnf server_req.cnf server_ext.cnf\n\n######################\n\ncd cms\n\nopenssl genrsa -out cms_ca.key 2048\n\ncat > cms_ca.cnf << 'EOF'\n[req]\ndistinguished_name = req_distinguished_name\nx509_extensions = v3_ca\nprompt = no\n\n[req_distinguished_name]\nCN = CMS Test CA\n\n[v3_ca]\nbasicConstraints = critical, CA:TRUE\nsubjectKeyIdentifier = hash\nauthorityKeyIdentifier = keyid:always,issuer:always\nkeyUsage = critical, keyCertSign, cRLSign\nEOF\n\nopenssl req -new -x509 -key cms_ca.key -out cms_ca.crt -days 3650 \\\n    -sha256 -config cms_ca.cnf\n\nopenssl genrsa -out cms.key 2048\n\ncat > cms_req.cnf << 'EOF'\n[req]\ndistinguished_name = req_distinguished_name\nprompt = no\n\n[req_distinguished_name]\nCN = cms1\nEOF\n\nopenssl req -new -key cms.key -out cms.csr -config cms_req.cnf\n\ncat > cms_ext.cnf << 'EOF'\n[v3_cms]\nbasicConstraints = critical, CA:FALSE\nsubjectKeyIdentifier = hash\nkeyUsage = digitalSignature, keyEncipherment, dataEncipherment, keyAgreement\nextendedKeyUsage = emailProtection\nEOF\n\nopenssl x509 -req -in cms.csr -CA cms_ca.crt -CAkey cms_ca.key -CAcreateserial \\\n    -out cms.crt -days 3650 -sha256 \\\n    -extfile cms_ext.cnf -extensions v3_cms\n\nprintf 'encrypted message\\n' > plaintext.txt\n\n# encrypted.p7m: envelope-encrypted to the CMS cert (no signature)\nopenssl cms -encrypt -binary -aes-256-cbc \\\n    -in plaintext.txt -outform DER -out encrypted.p7m \\\n    cms.crt\n\n# signed.p7m: signed with the CMS key (not encrypted)\nopenssl cms -sign -binary -nodetach \\\n    -inkey cms.key -signer cms.crt \\\n    -in plaintext.txt -outform DER -out signed.p7m\n\n# signed-encrypted.p7m: first sign, then encrypt the signed message\nopenssl cms -sign -binary -nodetach \\\n    -inkey cms.key -signer cms.crt \\\n    -in plaintext.txt -outform DER -out signed_inner.der\n\nopenssl cms -encrypt -binary -aes-256-cbc \\\n    -in signed_inner.der -inform DER -outform DER -out signed-encrypted.p7m \\\n    cms.crt\n\nopenssl pkcs12 -export -out keystore.p12 -inkey cms.key -in cms.crt \\\n    -password pass:cms \\\n    -certpbe PBE-SHA1-3DES \\\n    -keypbe PBE-SHA1-3DES \\\n    -macalg SHA1 \\\n    -certfile cms_ca.crt \\\n    -legacy\n\nrm -f cms_ca.key cms_ca.crt cms_ca.srl cms.key cms.crt cms.csr \\\n      cms_ca.cnf cms_req.cnf cms_ext.cnf plaintext.txt signed_inner.der\n"
  },
  {
    "path": "security-framework/test/server.key",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDUdbb5beIHeP1Z\nup4gZ1hPtgfN0frILyQSR2E40L8zXi/LPXUUquLuP7Z2HlFDVj0NxjjyBcyGX3fZ\nMg4IccMhtGPevrzfUi8ZzUm4Bf8BO535gOuWgDfB56bhY8D69vzb2KnKoUb6y/rl\n3KWM8r9eWNS3/Sk+y/kmBx9Lh4/mgl6RbqzpmGnGnl4UjlBhn6bDAUfsnX1CHqls\ntOUlXmDhI52Q+yGnyuESs/QLITdGz9lgKO184f6OcAaEpJ8hD+V5096+TR1nmv69\nkF6a7F0CmumNLgDUdi+aCC61SE7+mol0bP6UlH2Ux9NgKpHWiInztBfn5qGuZB4Q\nui3rcvJRAgMBAAECggEAAqnbNmaYXFd/MMVOQznbyCE1eSD69yXg+p4aAnvv9130\nujmcqVVbMP6mnABv7H4fwnJNP2qqEcHE7e8IJja+ZMfsbq6W7bNhH1O/oF1qC675\nQVdahL16DXh+Qvy6GW9YSXgz3eQ5Fdlx2BjqEKb7ALzbJazDDCGYn6oxfCP7Pmns\nbZ/pQy3h34lGPr3oBMGXLOmLtMOD92w6KBBPrA+BJdo3a9ZTkjsBkU0JmoEr+ZZA\nhEUKUivGRGUoYlYsqMaWri+LYuQyWg301yxXZxg22xfzzUpTo/APeUcw6dPjb2Xt\ns0TMIpkLitxk2wgO/cXZtfU3wEkvaO/zE+ijFVWDwQKBgQD2N4mLwmB8jPuoof9n\nByuq0e0anGa1NfVmlTqba234yKxD2VenzPzYQDv+xC3SXfgN+BvOt3Kei7sxKzt6\nXpFsGt5H7VKHITB5s/0omLRZsXwj2EBdTK0gA8mZuaSnXLFBolW3SuKU+iheojEZ\nVfmOz7C9Kl26M2LDUB46MBQ+EQKBgQDc5s7GpftxeSCIvi5RF9f3SwM/5H+ljVm1\nGlye0O9V5JctP2tQtSnLXr1/V4WWC+WiYyHsONdd1BvZRz4ba9QW46uPAfnNvlAe\nmipbtgM9mQoVnHsMf27vtnE09pye4+L0CJfZtruRyrLCQLR0MvH0F6SyeFSovFiC\nZn54g+wwQQKBgQCgCX1H8HISwviYpaOC7jA9+fFpyJsh0g7OPNU5TFzQxm7iMxU8\npor6bNYSRKWcBSREwC4i8S55S03DKdyhL3LKl7Q/gEySNMpzcMBucMNZQXn1Ooyr\nmDk3g/64Aui5OBCnHsMkPnKEbw1qZXYQh8eMQgcZDb6aVugtF5huLe4aYQKBgD1e\nhe2cKTnCG+7BXx66UA5ssY9rjKbSmSx+EWMxynwDUJiKeOboHZ9ZR638A6nGzloJ\nzl/Q/swbZE09xJxbnYVqZLwLIXouOBX4YHIwI8BWJv4QBgNX19sSxWqgZKyjxOZl\nCMK8SGnddUIQNdHeYWedtey7D1H9WV2I2fPjOpfBAoGAGcZmZaC0ClfIVkGrfrVM\noz/jXa7MfdLV0yaat3H9tQrW/DrRUdn5tGq0KBpvsCCnD8cqbj/wPlE9nxKfPTGs\nf5uOK1T6+18Xgq017iW9Gvb72J3W1/1NFpQGHjvKk4NcEUbpci8B0r/NK5rp4ayj\nY46z6PPnAVU3f+5PXbyVif8=\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "security-framework-sys/Cargo.toml",
    "content": "[package]\nname = \"security-framework-sys\"\nversion = \"2.17.1\"\nauthors = [\"Steven Fackler <sfackler@gmail.com>\", \"Kornel <kornel@geekhood.net>\"]\nlicense = \"MIT OR Apache-2.0\"\ndescription = \"Apple `Security.framework` low-level FFI bindings\"\nrepository = \"https://github.com/kornelski/rust-security-framework\"\nhomepage = \"https://lib.rs/crates/security-framework-sys\"\nreadme = \"README.md\"\nkeywords = [\"ffi\", \"iOS\", \"TLS\", \"SSL\", \"crypto\"]\ncategories = [\"os::macos-apis\", \"external-ffi-bindings\"]\nedition = \"2021\"\nrust-version = \"1.70\"\n\n[dependencies]\ncore-foundation-sys = \"0.8.7\"\nlibc = \"0.2.150\"\n\n[features]\ndefault = [\"OSX_10_13\"]\n# Always enabled. No-op.\nOSX_10_9 = []\n# Always enabled. No-op.\nOSX_10_10 = []\n# Always enabled. No-op.\nOSX_10_11 = []\n# Always enabled. No-op.\nOSX_10_12 = []\n# Always enabled. No-op.\nOSX_10_13 = []\n# Always enabled. No-op.\nOSX_10_14 = []\n# Enable APIs that require macOS 10.15\nOSX_10_15 = []\n# Enable features that require macOS 12\nmacos-12 = []\n\n[package.metadata.docs.rs]\ntargets = [\"x86_64-apple-darwin\", \"aarch64-apple-ios\"]\n\n[badges]\nmaintenance = { status = \"looking-for-maintainer\" }\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "security-framework-sys/src/access.rs",
    "content": "use core_foundation_sys::base::CFTypeID;\n\nextern \"C\" {\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecAccessGetTypeID() -> CFTypeID;\n}\n"
  },
  {
    "path": "security-framework-sys/src/access_control.rs",
    "content": "use core_foundation_sys::base::CFOptionFlags;\nuse core_foundation_sys::base::{CFAllocatorRef, CFTypeID, CFTypeRef};\nuse core_foundation_sys::error::CFErrorRef;\nuse core_foundation_sys::string::CFStringRef;\n\nuse crate::base::SecAccessControlRef;\n\nmod access_control_flags {\n    use super::CFOptionFlags;\n\n    pub const kSecAccessControlUserPresence: CFOptionFlags = 1 << 0;\n    pub const kSecAccessControlBiometryAny: CFOptionFlags = 1 << 1;\n    pub const kSecAccessControlBiometryCurrentSet: CFOptionFlags = 1 << 3;\n    pub const kSecAccessControlDevicePasscode: CFOptionFlags = 1 << 4;\n    #[cfg(feature = \"OSX_10_15\")]\n    pub const kSecAccessControlWatch: CFOptionFlags = 1 << 5;\n    pub const kSecAccessControlOr: CFOptionFlags = 1 << 14;\n    pub const kSecAccessControlAnd: CFOptionFlags = 1 << 15;\n    pub const kSecAccessControlPrivateKeyUsage: CFOptionFlags = 1 << 30;\n    pub const kSecAccessControlApplicationPassword: CFOptionFlags = 1 << 31;\n}\n\npub use access_control_flags::*;\n\nextern \"C\" {\n    pub static kSecAttrAccessibleWhenUnlocked: CFStringRef;\n    pub static kSecAttrAccessibleAfterFirstUnlock: CFStringRef;\n    pub static kSecAttrAccessibleAlways: CFStringRef;\n    pub static kSecAttrAccessibleWhenUnlockedThisDeviceOnly: CFStringRef;\n    pub static kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: CFStringRef;\n    pub static kSecAttrAccessibleAlwaysThisDeviceOnly: CFStringRef;\n    pub static kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: CFStringRef;\n}\n\nextern \"C\" {\n    pub fn SecAccessControlGetTypeID() -> CFTypeID;\n\n    pub fn SecAccessControlCreateWithFlags(\n        allocator: CFAllocatorRef,\n        protection: CFTypeRef,\n        flags: CFOptionFlags,\n        error: *mut CFErrorRef,\n    ) -> SecAccessControlRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/authorization.rs",
    "content": "use core_foundation_sys::base::{CFTypeRef, OSStatus};\nuse core_foundation_sys::bundle::CFBundleRef;\nuse core_foundation_sys::dictionary::CFDictionaryRef;\nuse core_foundation_sys::string::CFStringRef;\nuse std::os::raw::{c_char, c_void};\n\npub const errAuthorizationSuccess: OSStatus = 0;\npub const errAuthorizationInvalidSet: OSStatus = -60001;\npub const errAuthorizationInvalidRef: OSStatus = -60002;\npub const errAuthorizationInvalidTag: OSStatus = -60003;\npub const errAuthorizationInvalidPointer: OSStatus = -60004;\npub const errAuthorizationDenied: OSStatus = -60005;\npub const errAuthorizationCanceled: OSStatus = -60006;\npub const errAuthorizationInteractionNotAllowed: OSStatus = -60007;\npub const errAuthorizationInternal: OSStatus = -60008;\npub const errAuthorizationExternalizeNotAllowed: OSStatus = -60009;\npub const errAuthorizationInternalizeNotAllowed: OSStatus = -60010;\npub const errAuthorizationInvalidFlags: OSStatus = -60011;\npub const errAuthorizationToolExecuteFailure: OSStatus = -60031;\npub const errAuthorizationToolEnvironmentError: OSStatus = -60032;\npub const errAuthorizationBadAddress: OSStatus = -60033;\n\npub type AuthorizationFlags = u32;\npub const kAuthorizationFlagDefaults: AuthorizationFlags = 0;\npub const kAuthorizationFlagInteractionAllowed: AuthorizationFlags = 1;\npub const kAuthorizationFlagExtendRights: AuthorizationFlags = 2;\npub const kAuthorizationFlagPartialRights: AuthorizationFlags = 4;\npub const kAuthorizationFlagDestroyRights: AuthorizationFlags = 8;\npub const kAuthorizationFlagPreAuthorize: AuthorizationFlags = 16;\n\npub type AuthorizationRef = *mut c_void;\npub type AuthorizationString = *const c_char;\n\n#[repr(C)]\n#[derive(Copy, Clone, Debug)]\npub struct AuthorizationItem {\n    pub name: AuthorizationString,\n    pub valueLength: usize,\n    pub value: *mut c_void,\n    pub flags: u32,\n}\n\n#[repr(C)]\n#[derive(Copy, Clone, Debug)]\npub struct AuthorizationItemSet {\n    pub count: u32,\n    pub items: *mut AuthorizationItem,\n}\n\npub const kAuthorizationExternalFormLength: usize = 32;\n\n#[repr(C)]\n#[derive(Copy, Clone, Debug)]\npub struct AuthorizationExternalForm {\n    pub bytes: [c_char; kAuthorizationExternalFormLength],\n}\n\npub type AuthorizationRights = AuthorizationItemSet;\npub type AuthorizationEnvironment = AuthorizationItemSet;\n\npub type AuthorizationAsyncCallback =\n    unsafe extern \"C\" fn(err: OSStatus, blockAuthorizedRights: *mut AuthorizationRights);\n\nextern \"C\" {\n    pub fn AuthorizationCreate(\n        rights: *const AuthorizationRights,\n        environment: *const AuthorizationEnvironment,\n        flags: AuthorizationFlags,\n        authorization: *mut AuthorizationRef,\n    ) -> OSStatus;\n\n    pub fn AuthorizationFree(\n        authorization: AuthorizationRef,\n        flags: AuthorizationFlags,\n    ) -> OSStatus;\n\n    pub fn AuthorizationCopyRights(\n        authorization: AuthorizationRef,\n        rights: *const AuthorizationRights,\n        environment: *const AuthorizationEnvironment,\n        flags: AuthorizationFlags,\n        authorizedRights: *mut *mut AuthorizationRights,\n    ) -> OSStatus;\n\n    pub fn AuthorizationCopyRightsAsync(\n        authorization: AuthorizationRef,\n        rights: *const AuthorizationRights,\n        environment: *const AuthorizationEnvironment,\n        flags: AuthorizationFlags,\n        callbackBlock: AuthorizationAsyncCallback,\n    );\n\n    pub fn AuthorizationCopyInfo(\n        authorization: AuthorizationRef,\n        tag: AuthorizationString,\n        info: *mut *mut AuthorizationItemSet,\n    ) -> OSStatus;\n\n    pub fn AuthorizationMakeExternalForm(\n        authorization: AuthorizationRef,\n        extForm: *mut AuthorizationExternalForm,\n    ) -> OSStatus;\n\n    pub fn AuthorizationCreateFromExternalForm(\n        extForm: *const AuthorizationExternalForm,\n        authorization: *mut AuthorizationRef,\n    ) -> OSStatus;\n\n    pub fn AuthorizationFreeItemSet(set: *mut AuthorizationItemSet) -> OSStatus;\n\n    pub fn AuthorizationRightGet(\n        rightName: *const c_char,\n        rightDefinition: *mut CFDictionaryRef,\n    ) -> OSStatus;\n\n    pub fn AuthorizationRightSet(\n        authorization: AuthorizationRef,\n        rightName: *const c_char,\n        rightDefinition: CFTypeRef,\n        descriptionKey: CFStringRef,\n        bundle: CFBundleRef,\n        localeTableName: CFStringRef,\n    ) -> OSStatus;\n\n    pub fn AuthorizationRightRemove(\n        authorization: AuthorizationRef,\n        rightName: *const c_char,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn AuthorizationExecuteWithPrivileges(\n        authorization: AuthorizationRef,\n        pathToTool: *const c_char,\n        options: AuthorizationFlags,\n        arguments: *const *mut c_char,\n        communicationsPipe: *mut *mut libc::FILE,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn AuthorizationCopyPrivilegedReference(\n        authorization: *mut AuthorizationRef,\n        flags: AuthorizationFlags,\n    ) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/base.rs",
    "content": "use core_foundation_sys::base::OSStatus;\nuse core_foundation_sys::string::CFStringRef;\nuse std::os::raw::c_void;\n\npub enum OpaqueSecKeychainRef {}\n#[cfg(target_os = \"macos\")]\npub type SecKeychainRef = *mut OpaqueSecKeychainRef;\n\npub enum OpaqueSecKeychainItemRef {}\n#[cfg(target_os = \"macos\")]\npub type SecKeychainItemRef = *mut OpaqueSecKeychainItemRef;\n\n// OSType from MacTypes.h\n#[cfg(target_os = \"macos\")]\npub type SecKeychainAttrType = u32;\n\n#[repr(C)]\n#[derive(Copy, Clone)]\n#[cfg(target_os = \"macos\")]\npub struct SecKeychainAttribute {\n    pub tag: SecKeychainAttrType,\n    pub length: u32,\n    pub data: *mut c_void,\n}\n\n#[repr(C)]\n#[derive(Copy, Clone)]\n#[cfg(target_os = \"macos\")]\npub struct SecKeychainAttributeList {\n    pub count: u32,\n    pub attr: *mut SecKeychainAttribute,\n}\n\npub enum OpaqueSecCertificateRef {}\npub type SecCertificateRef = *mut OpaqueSecCertificateRef;\n\npub enum OpaqueSecAccessRef {}\n#[cfg(target_os = \"macos\")]\npub type SecAccessRef = *mut OpaqueSecAccessRef;\n\npub enum OpaqueSecAccessControlRef {}\npub type SecAccessControlRef = *mut OpaqueSecAccessControlRef;\n\npub enum OpaqueSecKeyRef {}\npub type SecKeyRef = *mut OpaqueSecKeyRef;\n\npub enum OpaqueSecIdentityRef {}\npub type SecIdentityRef = *mut OpaqueSecIdentityRef;\n\npub enum OpaqueSecPolicyRef {}\npub type SecPolicyRef = *mut OpaqueSecPolicyRef;\n\npub const errSecSuccess: OSStatus = 0;\npub const errSecUnimplemented: OSStatus = -4;\npub const errSecIO: OSStatus = -36;\npub const errSecParam: OSStatus = -50;\npub const errSecBadReq: OSStatus = -909;\npub const errSecNoTrustSettings: OSStatus = -25263;\npub const errSecAuthFailed: OSStatus = -25293;\npub const errSecDuplicateItem: OSStatus = -25299;\npub const errSecItemNotFound: OSStatus = -25300;\npub const errSecCreateChainFailed: OSStatus = -25318;\npub const errSecConversionError: OSStatus = -67594;\npub const errSecHostNameMismatch: OSStatus = -67602;\npub const errSecInvalidExtendedKeyUsage: OSStatus = -67609;\npub const errSecTrustSettingDeny: OSStatus = -67654;\npub const errSecCertificateRevoked: OSStatus = -67820;\npub const errSecNotTrusted: OSStatus = -67843;\npub const errSecInternalComponent: OSStatus = -2070;\n\nextern \"C\" {\n    // this is available on iOS 11.3+, MacOS 10.3+\n    pub fn SecCopyErrorMessageString(status: OSStatus, reserved: *mut c_void) -> CFStringRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/certificate.rs",
    "content": "use core_foundation_sys::array::CFArrayRef;\nuse core_foundation_sys::base::{CFAllocatorRef, CFTypeID, OSStatus};\nuse core_foundation_sys::data::CFDataRef;\n#[cfg(target_os = \"macos\")]\nuse crate::base::SecKeychainRef;\n#[cfg(target_os = \"macos\")]\nuse core_foundation_sys::dictionary::CFDictionaryRef;\nuse core_foundation_sys::error::CFErrorRef;\nuse core_foundation_sys::string::CFStringRef;\n\nuse crate::base::{SecCertificateRef, SecKeyRef};\n\nextern \"C\" {\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyKeyType: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyKeyLabel: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyKeyLocalizedLabel: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyKeyValue: CFStringRef;\n\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyTypeWarning: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyTypeSuccess: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyTypeSection: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyTypeData: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyTypeString: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyTypeURL: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPropertyTypeDate: CFStringRef;\n\n    // certificate policies\n    pub static kSecPolicyAppleX509Basic: CFStringRef;\n    pub static kSecPolicyAppleSSL: CFStringRef;\n    pub static kSecPolicyAppleSMIME: CFStringRef;\n    pub static kSecPolicyAppleEAP: CFStringRef;\n    pub static kSecPolicyAppleIPsec: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPolicyApplePKINITClient: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecPolicyApplePKINITServer: CFStringRef;\n    pub static kSecPolicyAppleCodeSigning: CFStringRef;\n    pub static kSecPolicyMacAppStoreReceipt: CFStringRef;\n    pub static kSecPolicyAppleIDValidation: CFStringRef;\n    pub static kSecPolicyAppleTimeStamping: CFStringRef;\n    pub static kSecPolicyAppleRevocation: CFStringRef;\n    pub static kSecPolicyApplePassbookSigning: CFStringRef;\n    pub static kSecPolicyApplePayIssuerEncryption: CFStringRef;\n\n    pub fn SecCertificateGetTypeID() -> CFTypeID;\n    pub fn SecCertificateCreateWithData(\n        allocator: CFAllocatorRef,\n        data: CFDataRef,\n    ) -> SecCertificateRef;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecCertificateAddToKeychain(\n        certificate: SecCertificateRef,\n        keychain: SecKeychainRef,\n    ) -> OSStatus;\n    pub fn SecCertificateCopyData(certificate: SecCertificateRef) -> CFDataRef;\n    pub fn SecCertificateCopySubjectSummary(certificate: SecCertificateRef) -> CFStringRef;\n    pub fn SecCertificateCopyCommonName(\n        certificate: SecCertificateRef,\n        common_name: *mut CFStringRef,\n    ) -> OSStatus;\n    pub fn SecCertificateCopyEmailAddresses(\n        certificate: SecCertificateRef,\n        email_addresses: *mut CFArrayRef,\n    ) -> OSStatus;\n\n    pub fn SecCertificateCopyNormalizedIssuerSequence(certificate: SecCertificateRef) -> CFDataRef;\n\n    pub fn SecCertificateCopyNormalizedSubjectSequence(certificate: SecCertificateRef)\n        -> CFDataRef;\n    #[cfg(target_os = \"macos\")]\n    #[cfg_attr(target_arch = \"aarch64\", link_name = \"SecCertificateCopyPublicKey$LEGACYMAC\")]\n    #[deprecated(note = \"Deprecated by Apple. May not work any more. Use SecCertificateCopyKey\")]\n    pub fn SecCertificateCopyPublicKey(\n        certificate: SecCertificateRef,\n        key: *mut SecKeyRef,\n    ) -> OSStatus;\n    pub fn SecCertificateCopyKey(certificate: SecCertificateRef) -> SecKeyRef;\n    pub fn SecCertificateCopySerialNumberData(\n        certificate: SecCertificateRef,\n        error: *mut CFErrorRef,\n    ) -> CFDataRef;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecCertificateCopyValues(\n        certificate: SecCertificateRef,\n        keys: CFArrayRef,\n        error: *mut CFErrorRef,\n    ) -> CFDictionaryRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/certificate_oids.rs",
    "content": "use core_foundation_sys::string::CFStringRef;\n\nextern \"C\" {\n    pub static kSecOIDX509V1SignatureAlgorithm: CFStringRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/cipher_suite.rs",
    "content": "#[cfg(not(target_os = \"macos\"))]\npub type SSLCipherSuite = u16;\n\n#[cfg(all(target_os = \"macos\", target_arch = \"aarch64\"))]\npub type SSLCipherSuite = u16;\n\n#[cfg(all(target_os = \"macos\", not(target_arch = \"aarch64\")))]\npub type SSLCipherSuite = u32;\n\npub const SSL_NULL_WITH_NULL_NULL: SSLCipherSuite = 0x0000;\npub const SSL_RSA_WITH_NULL_MD5: SSLCipherSuite = 0x0001;\npub const SSL_RSA_WITH_NULL_SHA: SSLCipherSuite = 0x0002;\npub const SSL_RSA_EXPORT_WITH_RC4_40_MD5: SSLCipherSuite = 0x0003;\npub const SSL_RSA_WITH_RC4_128_MD5: SSLCipherSuite = 0x0004;\npub const SSL_RSA_WITH_RC4_128_SHA: SSLCipherSuite = 0x0005;\npub const SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: SSLCipherSuite = 0x0006;\npub const SSL_RSA_WITH_IDEA_CBC_SHA: SSLCipherSuite = 0x0007;\npub const SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: SSLCipherSuite = 0x0008;\npub const SSL_RSA_WITH_DES_CBC_SHA: SSLCipherSuite = 0x0009;\npub const SSL_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x000A;\npub const SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: SSLCipherSuite = 0x000B;\npub const SSL_DH_DSS_WITH_DES_CBC_SHA: SSLCipherSuite = 0x000C;\npub const SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x000D;\npub const SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: SSLCipherSuite = 0x000E;\npub const SSL_DH_RSA_WITH_DES_CBC_SHA: SSLCipherSuite = 0x000F;\npub const SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x0010;\npub const SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: SSLCipherSuite = 0x0011;\npub const SSL_DHE_DSS_WITH_DES_CBC_SHA: SSLCipherSuite = 0x0012;\npub const SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x0013;\npub const SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: SSLCipherSuite = 0x0014;\npub const SSL_DHE_RSA_WITH_DES_CBC_SHA: SSLCipherSuite = 0x0015;\npub const SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x0016;\npub const SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: SSLCipherSuite = 0x0017;\npub const SSL_DH_anon_WITH_RC4_128_MD5: SSLCipherSuite = 0x0018;\npub const SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: SSLCipherSuite = 0x0019;\npub const SSL_DH_anon_WITH_DES_CBC_SHA: SSLCipherSuite = 0x001A;\npub const SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x001B;\npub const SSL_FORTEZZA_DMS_WITH_NULL_SHA: SSLCipherSuite = 0x001C;\npub const SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: SSLCipherSuite = 0x001D;\n\n// TLS addenda using AES, per RFC 3268\npub const TLS_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x002F;\npub const TLS_DH_DSS_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0030;\npub const TLS_DH_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0031;\npub const TLS_DHE_DSS_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0032;\npub const TLS_DHE_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0033;\npub const TLS_DH_anon_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0034;\npub const TLS_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0035;\npub const TLS_DH_DSS_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0036;\npub const TLS_DH_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0037;\npub const TLS_DHE_DSS_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0038;\npub const TLS_DHE_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0039;\npub const TLS_DH_anon_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x003A;\n\n// ECDSA addenda, RFC 4492\npub const TLS_ECDH_ECDSA_WITH_NULL_SHA: SSLCipherSuite = 0xC001;\npub const TLS_ECDH_ECDSA_WITH_RC4_128_SHA: SSLCipherSuite = 0xC002;\npub const TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0xC003;\npub const TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0xC004;\npub const TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0xC005;\npub const TLS_ECDHE_ECDSA_WITH_NULL_SHA: SSLCipherSuite = 0xC006;\npub const TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: SSLCipherSuite = 0xC007;\npub const TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0xC008;\npub const TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0xC009;\npub const TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0xC00A;\npub const TLS_ECDH_RSA_WITH_NULL_SHA: SSLCipherSuite = 0xC00B;\npub const TLS_ECDH_RSA_WITH_RC4_128_SHA: SSLCipherSuite = 0xC00C;\npub const TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0xC00D;\npub const TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0xC00E;\npub const TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0xC00F;\npub const TLS_ECDHE_RSA_WITH_NULL_SHA: SSLCipherSuite = 0xC010;\npub const TLS_ECDHE_RSA_WITH_RC4_128_SHA: SSLCipherSuite = 0xC011;\npub const TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0xC012;\npub const TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0xC013;\npub const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0xC014;\npub const TLS_ECDH_anon_WITH_NULL_SHA: SSLCipherSuite = 0xC015;\npub const TLS_ECDH_anon_WITH_RC4_128_SHA: SSLCipherSuite = 0xC016;\npub const TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0xC017;\npub const TLS_ECDH_anon_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0xC018;\npub const TLS_ECDH_anon_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0xC019;\n\n// TLS 1.2 addenda, RFC 5246\n\n// Initial state.\npub const TLS_NULL_WITH_NULL_NULL: SSLCipherSuite = 0x0000;\n\n// Server provided RSA certificate for key exchange.\npub const TLS_RSA_WITH_NULL_MD5: SSLCipherSuite = 0x0001;\npub const TLS_RSA_WITH_NULL_SHA: SSLCipherSuite = 0x0002;\npub const TLS_RSA_WITH_RC4_128_MD5: SSLCipherSuite = 0x0004;\npub const TLS_RSA_WITH_RC4_128_SHA: SSLCipherSuite = 0x0005;\npub const TLS_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x000A;\n// pub const TLS_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x002F;\n// pub const TLS_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0035;\npub const TLS_RSA_WITH_NULL_SHA256: SSLCipherSuite = 0x003B;\npub const TLS_RSA_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x003C;\npub const TLS_RSA_WITH_AES_256_CBC_SHA256: SSLCipherSuite = 0x003D;\n\n// Server-authenticated (and optionally client-authenticated) Diffie-Hellman.\npub const TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x000D;\npub const TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x0010;\npub const TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x0013;\npub const TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x0016;\n// pub const TLS_DH_DSS_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0030;\n// pub const TLS_DH_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0031;\n// pub const TLS_DHE_DSS_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0032;\n// pub const TLS_DHE_RSA_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0033;\n// pub const TLS_DH_DSS_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0036;\n// pub const TLS_DH_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0037;\n// pub const TLS_DHE_DSS_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0038;\n// pub const TLS_DHE_RSA_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0039;\npub const TLS_DH_DSS_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x003E;\npub const TLS_DH_RSA_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x003F;\npub const TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x0040;\npub const TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x0067;\npub const TLS_DH_DSS_WITH_AES_256_CBC_SHA256: SSLCipherSuite = 0x0068;\npub const TLS_DH_RSA_WITH_AES_256_CBC_SHA256: SSLCipherSuite = 0x0069;\npub const TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: SSLCipherSuite = 0x006A;\npub const TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: SSLCipherSuite = 0x006B;\n\n// Completely anonymous Diffie-Hellman\npub const TLS_DH_anon_WITH_RC4_128_MD5: SSLCipherSuite = 0x0018;\npub const TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x001B;\n// pub const TLS_DH_anon_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0034;\n// pub const TLS_DH_anon_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x003A;\npub const TLS_DH_anon_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x006C;\npub const TLS_DH_anon_WITH_AES_256_CBC_SHA256: SSLCipherSuite = 0x006D;\n\n// Addendum from RFC 4279, TLS PSK\n\npub const TLS_PSK_WITH_RC4_128_SHA: SSLCipherSuite = 0x008A;\npub const TLS_PSK_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x008B;\npub const TLS_PSK_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x008C;\npub const TLS_PSK_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x008D;\npub const TLS_DHE_PSK_WITH_RC4_128_SHA: SSLCipherSuite = 0x008E;\npub const TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x008F;\npub const TLS_DHE_PSK_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0090;\npub const TLS_DHE_PSK_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0091;\npub const TLS_RSA_PSK_WITH_RC4_128_SHA: SSLCipherSuite = 0x0092;\npub const TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: SSLCipherSuite = 0x0093;\npub const TLS_RSA_PSK_WITH_AES_128_CBC_SHA: SSLCipherSuite = 0x0094;\npub const TLS_RSA_PSK_WITH_AES_256_CBC_SHA: SSLCipherSuite = 0x0095;\n\n// RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption\n\npub const TLS_PSK_WITH_NULL_SHA: SSLCipherSuite = 0x002C;\npub const TLS_DHE_PSK_WITH_NULL_SHA: SSLCipherSuite = 0x002D;\npub const TLS_RSA_PSK_WITH_NULL_SHA: SSLCipherSuite = 0x002E;\n\n// Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites\n// for TLS.\npub const TLS_RSA_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x009C;\npub const TLS_RSA_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x009D;\npub const TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x009E;\npub const TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x009F;\npub const TLS_DH_RSA_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x00A0;\npub const TLS_DH_RSA_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x00A1;\npub const TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x00A2;\npub const TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x00A3;\npub const TLS_DH_DSS_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x00A4;\npub const TLS_DH_DSS_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x00A5;\npub const TLS_DH_anon_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x00A6;\npub const TLS_DH_anon_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x00A7;\n\n// RFC 5487 - PSK with SHA-256/384 and AES GCM\npub const TLS_PSK_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x00A8;\npub const TLS_PSK_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x00A9;\npub const TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x00AA;\npub const TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x00AB;\npub const TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0x00AC;\npub const TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0x00AD;\n\npub const TLS_PSK_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x00AE;\npub const TLS_PSK_WITH_AES_256_CBC_SHA384: SSLCipherSuite = 0x00AF;\npub const TLS_PSK_WITH_NULL_SHA256: SSLCipherSuite = 0x00B0;\npub const TLS_PSK_WITH_NULL_SHA384: SSLCipherSuite = 0x00B1;\n\npub const TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x00B2;\npub const TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: SSLCipherSuite = 0x00B3;\npub const TLS_DHE_PSK_WITH_NULL_SHA256: SSLCipherSuite = 0x00B4;\npub const TLS_DHE_PSK_WITH_NULL_SHA384: SSLCipherSuite = 0x00B5;\n\npub const TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0x00B6;\npub const TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: SSLCipherSuite = 0x00B7;\npub const TLS_RSA_PSK_WITH_NULL_SHA256: SSLCipherSuite = 0x00B8;\npub const TLS_RSA_PSK_WITH_NULL_SHA384: SSLCipherSuite = 0x00B9;\n\n// Addenda from rfc 5289  Elliptic Curve Cipher Suites with\n// HMAC SHA-256/384.\npub const TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0xC023;\npub const TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: SSLCipherSuite = 0xC024;\npub const TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0xC025;\npub const TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: SSLCipherSuite = 0xC026;\npub const TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0xC027;\npub const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: SSLCipherSuite = 0xC028;\npub const TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: SSLCipherSuite = 0xC029;\npub const TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: SSLCipherSuite = 0xC02A;\n\n// Addenda from rfc 5289  Elliptic Curve Cipher Suites with\n// SHA-256/384 and AES Galois Counter Mode (GCM)\npub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0xC02B;\npub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0xC02C;\npub const TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0xC02D;\npub const TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0xC02E;\npub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0xC02F;\npub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0xC030;\npub const TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: SSLCipherSuite = 0xC031;\npub const TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: SSLCipherSuite = 0xC032;\n\n// RFC 5746 - Secure Renegotiation\npub const TLS_EMPTY_RENEGOTIATION_INFO_SCSV: SSLCipherSuite = 0x00FF;\n// Tags for SSL 2 cipher kinds which are not specified\n// for SSL 3.\n//\npub const SSL_RSA_WITH_RC2_CBC_MD5: SSLCipherSuite = 0xFF80;\npub const SSL_RSA_WITH_IDEA_CBC_MD5: SSLCipherSuite = 0xFF81;\npub const SSL_RSA_WITH_DES_CBC_MD5: SSLCipherSuite = 0xFF82;\npub const SSL_RSA_WITH_3DES_EDE_CBC_MD5: SSLCipherSuite = 0xFF83;\npub const SSL_NO_SUCH_CIPHERSUITE: SSLCipherSuite = 0xFFFF;\n"
  },
  {
    "path": "security-framework-sys/src/cms.rs",
    "content": "//! Cryptographic Message Syntax support\n\nuse std::os::raw::c_void;\n\nuse core_foundation_sys::array::CFArrayRef;\nuse core_foundation_sys::base::{Boolean, CFTypeID, CFTypeRef, OSStatus};\nuse core_foundation_sys::data::CFDataRef;\nuse core_foundation_sys::date::CFAbsoluteTime;\nuse core_foundation_sys::string::CFStringRef;\n\nuse crate::base::SecCertificateRef;\nuse crate::trust::SecTrustRef;\n\npub enum OpaqueCMSEncoderRef {}\npub type CMSEncoderRef = *mut OpaqueCMSEncoderRef;\n\npub enum OpaqueCMSDecoderRef {}\npub type CMSDecoderRef = *mut OpaqueCMSEncoderRef;\n\n#[repr(i32)]\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum CMSSignerStatus {\n    kCMSSignerUnsigned = 0,\n    kCMSSignerValid = 1,\n    kCMSSignerNeedsDetachedContent = 2,\n    kCMSSignerInvalidSignature = 3,\n    kCMSSignerInvalidCert = 4,\n    kCMSSignerInvalidIndex = 5,\n}\n\npub type CMSSignedAttributes = u32;\npub const kCMSAttrNone: CMSSignedAttributes = 0x0000;\npub const kCMSAttrSmimeCapabilities: CMSSignedAttributes = 0x0001;\npub const kCMSAttrSmimeEncryptionKeyPrefs: CMSSignedAttributes = 0x0002;\npub const kCMSAttrSmimeMSEncryptionKeyPrefs: CMSSignedAttributes = 0x0004;\npub const kCMSAttrSigningTime: CMSSignedAttributes = 0x0008;\npub const kCMSAttrAppleCodesigningHashAgility: CMSSignedAttributes = 0x0010;\npub const kCMSAttrAppleCodesigningHashAgilityV2: CMSSignedAttributes = 0x0020;\npub const kCMSAttrAppleExpirationTime: CMSSignedAttributes = 0x0040;\n\n#[repr(i32)]\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum CMSCertificateChainMode {\n    kCMSCertificateNone = 0,\n    kCMSCertificateSignerOnly = 1,\n    kCMSCertificateChain = 2,\n    kCMSCertificateChainWithRoot = 3,\n    kCMSCertificateChainWithRootOrFail = 4,\n}\n\nextern \"C\" {\n\n    // CMS decoder\n\n    pub fn CMSDecoderGetTypeID() -> CFTypeID;\n\n    pub fn CMSDecoderCreate(output: *mut CMSDecoderRef) -> OSStatus;\n\n    pub fn CMSDecoderUpdateMessage(\n        decoder: CMSDecoderRef,\n        msg_bytes: *const c_void,\n        msg_bytes_len: usize,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderFinalizeMessage(decoder: CMSDecoderRef) -> OSStatus;\n\n    pub fn CMSDecoderSetDetachedContent(\n        decoder: CMSDecoderRef,\n        detached_content: CFDataRef,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopyDetachedContent(\n        decoder: CMSDecoderRef,\n        detached_content_out: *mut CFDataRef,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderGetNumSigners(\n        decoder: CMSDecoderRef,\n        num_signers_out: *mut usize,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopySignerStatus(\n        decoder: CMSDecoderRef,\n        signer_index: usize,\n        policy_or_array: CFTypeRef,\n        evaluate_sec_trust: Boolean,\n        signer_status_out: *mut CMSSignerStatus,\n        sec_trust_out: *mut SecTrustRef,\n        cert_verify_result_code_out: *mut OSStatus,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopySignerEmailAddress(\n        decoder: CMSDecoderRef,\n        signer_index: usize,\n        signer_email_address_out: *mut CFStringRef,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopySignerCert(\n        decoder: CMSDecoderRef,\n        signer_index: usize,\n        signer_cert_out: *mut SecCertificateRef,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderIsContentEncrypted(\n        decoder: CMSDecoderRef,\n        is_encrypted_out: *mut Boolean,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopyEncapsulatedContentType(\n        decoder: CMSDecoderRef,\n        content_type_out: *mut CFDataRef,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopyAllCerts(decoder: CMSDecoderRef, certs_out: *mut CFArrayRef) -> OSStatus;\n\n    pub fn CMSDecoderCopyContent(decoder: CMSDecoderRef, content_out: *mut CFDataRef) -> OSStatus;\n\n    pub fn CMSDecoderCopySignerSigningTime(\n        decoder: CMSDecoderRef,\n        signer_index: usize,\n        sign_time_out: *mut CFAbsoluteTime,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopySignerTimestamp(\n        decoder: CMSDecoderRef,\n        signer_index: usize,\n        timestamp: *mut CFAbsoluteTime,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopySignerTimestampWithPolicy(\n        decoder: CMSDecoderRef,\n        timestamp_policy: CFTypeRef,\n        signer_index: usize,\n        timestamp: *mut CFAbsoluteTime,\n    ) -> OSStatus;\n\n    pub fn CMSDecoderCopySignerTimestampCertificates(\n        decoder: CMSDecoderRef,\n        signer_index: usize,\n        certificate_refs: *mut CFArrayRef,\n    ) -> OSStatus;\n\n    // CMS encoder\n\n    pub static kCMSEncoderDigestAlgorithmSHA1: CFStringRef;\n    pub static kCMSEncoderDigestAlgorithmSHA256: CFStringRef;\n\n    pub fn CMSEncoderGetTypeID() -> CFTypeID;\n\n    pub fn CMSEncoderCreate(encoder_out: *mut CMSEncoderRef) -> OSStatus;\n\n    pub fn CMSEncoderSetSignerAlgorithm(\n        encoder: CMSEncoderRef,\n        digest_alogrithm: CFStringRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderAddSigners(encoder: CMSEncoderRef, signer_or_array: CFTypeRef) -> OSStatus;\n\n    pub fn CMSEncoderCopySigners(encoder: CMSEncoderRef, signers_out: *mut CFArrayRef) -> OSStatus;\n\n    pub fn CMSEncoderAddRecipients(\n        encoder: CMSEncoderRef,\n        recipient_or_array: CFTypeRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderCopyRecipients(\n        encoder: CMSEncoderRef,\n        recipients_out: *mut CFArrayRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderSetHasDetachedContent(\n        encoder: CMSEncoderRef,\n        detached_content: Boolean,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderGetHasDetachedContent(\n        encoder: CMSEncoderRef,\n        detached_content_out: *mut Boolean,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderSetEncapsulatedContentTypeOID(\n        encoder: CMSEncoderRef,\n        content_type_oid: CFTypeRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderCopyEncapsulatedContentType(\n        encoder: CMSEncoderRef,\n        content_type_out: *mut CFDataRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderAddSupportingCerts(\n        encoder: CMSEncoderRef,\n        cert_or_array: CFTypeRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderCopySupportingCerts(\n        encoder: CMSEncoderRef,\n        certs_out: *mut CFArrayRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderAddSignedAttributes(\n        encoder: CMSEncoderRef,\n        signed_attributes: CMSSignedAttributes,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderSetCertificateChainMode(\n        encoder: CMSEncoderRef,\n        chain_mode: CMSCertificateChainMode,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderGetCertificateChainMode(\n        encoder: CMSEncoderRef,\n        chain_mode_out: *mut CMSCertificateChainMode,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderUpdateContent(\n        encoder: CMSEncoderRef,\n        content: *const c_void,\n        content_len: usize,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderCopyEncodedContent(\n        encoder: CMSEncoderRef,\n        encoded_content_out: *mut CFDataRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncodeContent(\n        signers: CFTypeRef,\n        recipients: CFTypeRef,\n        content_type_oid: CFTypeRef,\n        detached_content: Boolean,\n        signed_attributes: CMSSignedAttributes,\n        content: *const c_void,\n        content_len: usize,\n        encoded_content_out: *mut CFDataRef,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderCopySignerTimestamp(\n        encoder: CMSEncoderRef,\n        signer_index: usize,\n        timestamp: *mut CFAbsoluteTime,\n    ) -> OSStatus;\n\n    pub fn CMSEncoderCopySignerTimestampWithPolicy(\n        encoder: CMSEncoderRef,\n        timestamp_policy: CFTypeRef,\n        signer_index: usize,\n        timestamp: *mut CFAbsoluteTime,\n    ) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/code_signing.rs",
    "content": "use core_foundation_sys::base::{CFTypeID, OSStatus};\nuse core_foundation_sys::dictionary::CFDictionaryRef;\nuse core_foundation_sys::string::CFStringRef;\nuse core_foundation_sys::url::CFURLRef;\n\npub enum OpaqueSecRequirementRef {}\npub type SecRequirementRef = *mut OpaqueSecRequirementRef;\n\npub enum OpaqueSecCodeRef {}\npub type SecCodeRef = *mut OpaqueSecCodeRef;\n\npub enum OpaqueSecStaticCodeRef {}\npub type SecStaticCodeRef = *mut OpaqueSecStaticCodeRef;\n\npub type SecCSFlags = u32;\npub const kSecCSCheckAllArchitectures: SecCSFlags = 1 << 0;\npub const kSecCSDoNotValidateExecutable: SecCSFlags = 1 << 1;\npub const kSecCSDoNotValidateResources: SecCSFlags = 1 << 2;\npub const kSecCSBasicValidateOnly: SecCSFlags = kSecCSDoNotValidateExecutable | kSecCSDoNotValidateResources;\npub const kSecCSCheckNestedCode: SecCSFlags = 1 << 3;\npub const kSecCSStrictValidate: SecCSFlags = 1 << 4;\npub const kSecCSFullReport: SecCSFlags = 1 << 5;\npub const kSecCSCheckGatekeeperArchitectures: SecCSFlags = (1 << 6) | kSecCSCheckAllArchitectures;\npub const kSecCSRestrictSymlinks: SecCSFlags = 1 << 7;\npub const kSecCSRestrictToAppLike: SecCSFlags = 1 << 8;\npub const kSecCSRestrictSidebandData: SecCSFlags = 1 << 9;\npub const kSecCSUseSoftwareSigningCert: SecCSFlags = 1 << 10;\npub const kSecCSValidatePEH: SecCSFlags = 1 << 11;\npub const kSecCSSingleThreaded: SecCSFlags = 1 << 12;\n// 13 - 15 are unused\n// This is only available in macOS 11.3:\n// pub const kSecCSAllowNetworkAccess: SecCSFlags = 1 << 16;\n// 17 - 25 are unused\npub const kSecCSQuickCheck: SecCSFlags = 1 << 26;\npub const kSecCSCheckTrustedAnchors: SecCSFlags = 1 << 27;\npub const kSecCSReportProgress: SecCSFlags = 1 << 28;\npub const kSecCSNoNetworkAccess: SecCSFlags = 1 << 29;\npub const kSecCSEnforceRevocationChecks: SecCSFlags = 1 << 30;\npub const kSecCSConsiderExpiration: SecCSFlags = 1 << 31;\n\nextern \"C\" {\n    pub static kSecGuestAttributeArchitecture: CFStringRef;\n    pub static kSecGuestAttributeAudit: CFStringRef;\n    pub static kSecGuestAttributeCanonical: CFStringRef;\n    pub static kSecGuestAttributeDynamicCode: CFStringRef;\n    pub static kSecGuestAttributeDynamicCodeInfoPlist: CFStringRef;\n    pub static kSecGuestAttributeHash: CFStringRef;\n    pub static kSecGuestAttributeMachPort: CFStringRef;\n    pub static kSecGuestAttributePid: CFStringRef;\n    pub static kSecGuestAttributeSubarchitecture: CFStringRef;\n\n    pub fn SecCodeGetTypeID() -> CFTypeID;\n    pub fn SecStaticCodeGetTypeID() -> CFTypeID;\n    pub fn SecRequirementGetTypeID() -> CFTypeID;\n\n    pub fn SecCodeCheckValidity(\n        code: SecCodeRef,\n        flags: SecCSFlags,\n        requirement: SecRequirementRef,\n    ) -> OSStatus;\n\n    pub fn SecCodeCopyGuestWithAttributes(\n        host: SecCodeRef,\n        attrs: CFDictionaryRef,\n        flags: SecCSFlags,\n        guest: *mut SecCodeRef,\n    ) -> OSStatus;\n\n    pub fn SecCodeCopyPath(\n        code: SecStaticCodeRef,\n        flags: SecCSFlags,\n        path: *mut CFURLRef,\n    ) -> OSStatus;\n\n    pub fn SecCodeCopySelf(flags: SecCSFlags, out: *mut SecCodeRef) -> OSStatus;\n\n    pub fn SecRequirementCreateWithString(\n        text: CFStringRef,\n        flags: SecCSFlags,\n        requirement: *mut SecRequirementRef,\n    ) -> OSStatus;\n\n    pub fn SecStaticCodeCheckValidity(\n        code: SecStaticCodeRef,\n        flags: SecCSFlags,\n        requirement: SecRequirementRef,\n    ) -> OSStatus;\n\n    pub fn SecStaticCodeCreateWithPath(\n        path: CFURLRef,\n        flags: SecCSFlags,\n        code: *mut SecStaticCodeRef,\n    ) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/digest_transform.rs",
    "content": "use core_foundation_sys::base::{CFIndex, CFTypeRef};\nuse core_foundation_sys::error::CFErrorRef;\nuse core_foundation_sys::string::CFStringRef;\n\nuse crate::transform::SecTransformRef;\n\nextern \"C\" {\n    pub static kSecDigestHMACKeyAttribute: CFStringRef;\n    pub static kSecDigestHMACMD5: CFStringRef;\n    pub static kSecDigestHMACSHA1: CFStringRef;\n    pub static kSecDigestHMACSHA2: CFStringRef;\n    pub static kSecDigestLengthAttribute: CFStringRef;\n    pub static kSecDigestMD2: CFStringRef;\n    pub static kSecDigestMD4: CFStringRef;\n    pub static kSecDigestMD5: CFStringRef;\n    pub static kSecDigestSHA1: CFStringRef;\n    pub static kSecDigestSHA2: CFStringRef;\n    pub static kSecDigestTypeAttribute: CFStringRef;\n\n    #[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\n    pub fn SecDigestTransformCreate(\n        digestType: CFTypeRef,\n        digestLength: CFIndex,\n        error: *mut CFErrorRef,\n    ) -> SecTransformRef;\n\n// this symbol is apparently missing in 10.13.3?\n// pub fn SecDigestTransformGetTypeID() -> CFTypeID;\n}\n"
  },
  {
    "path": "security-framework-sys/src/encrypt_transform.rs",
    "content": "use core_foundation_sys::error::CFErrorRef;\nuse core_foundation_sys::string::CFStringRef;\n\nuse crate::base::SecKeyRef;\nuse crate::transform::SecTransformRef;\n\nextern \"C\" {\n    pub static kSecEncryptionMode: CFStringRef;\n    pub static kSecEncryptKey: CFStringRef;\n    pub static kSecIVKey: CFStringRef;\n    pub static kSecModeCBCKey: CFStringRef;\n    pub static kSecModeCFBKey: CFStringRef;\n    pub static kSecModeECBKey: CFStringRef;\n    pub static kSecModeNoneKey: CFStringRef;\n    pub static kSecModeOFBKey: CFStringRef;\n    pub static kSecPaddingKey: CFStringRef;\n    pub static kSecPaddingNoneKey: CFStringRef;\n    pub static kSecPaddingOAEPKey: CFStringRef;\n    pub static kSecPaddingPKCS1Key: CFStringRef;\n    pub static kSecPaddingPKCS5Key: CFStringRef;\n    pub static kSecPaddingPKCS7Key: CFStringRef;\n\n    #[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\n    pub fn SecDecryptTransformCreate(keyRef: SecKeyRef, error: *mut CFErrorRef) -> SecTransformRef;\n    // this symbol is apparently missing in 10.13.3?\n    // pub fn SecDecryptTransformGetTypeID() -> CFTypeID;\n    #[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\n    pub fn SecEncryptTransformCreate(keyRef: SecKeyRef, error: *mut CFErrorRef) -> SecTransformRef;\n// this symbol is apparently missing in 10.13.3?\n// pub fn SecEncryptTransformGetTypeID() -> CFTypeID;\n}\n"
  },
  {
    "path": "security-framework-sys/src/identity.rs",
    "content": "#[cfg(target_os = \"macos\")]\nuse core_foundation_sys::base::CFTypeRef;\nuse core_foundation_sys::base::{CFTypeID, OSStatus};\n\nuse crate::base::{SecCertificateRef, SecIdentityRef, SecKeyRef};\n\nextern \"C\" {\n    pub fn SecIdentityGetTypeID() -> CFTypeID;\n    pub fn SecIdentityCopyCertificate(\n        identity: SecIdentityRef,\n        certificate_ref: *mut SecCertificateRef,\n    ) -> OSStatus;\n    pub fn SecIdentityCopyPrivateKey(identity: SecIdentityRef, key_ref: *mut SecKeyRef)\n        -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecIdentityCreateWithCertificate(\n        keychain_or_Array: CFTypeRef,\n        certificate_ref: SecCertificateRef,\n        identity_ref: *mut SecIdentityRef,\n    ) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/import_export.rs",
    "content": "use core_foundation_sys::array::CFArrayRef;\n#[cfg(target_os = \"macos\")]\nuse core_foundation_sys::base::CFTypeRef;\nuse core_foundation_sys::base::OSStatus;\nuse core_foundation_sys::data::CFDataRef;\nuse core_foundation_sys::dictionary::CFDictionaryRef;\nuse core_foundation_sys::string::CFStringRef;\n#[cfg(target_os = \"macos\")]\nuse std::os::raw::c_uint;\n\n#[cfg(target_os = \"macos\")]\nuse crate::base::{SecAccessRef, SecKeychainRef};\n\n#[cfg(target_os = \"macos\")]\n/// <https://developer.apple.com/documentation/security/secexternalformat>\npub type SecExternalFormat = u32;\n#[cfg(target_os = \"macos\")]\npub type SecExternalItemType = u32;\n#[cfg(target_os = \"macos\")]\npub type SecItemImportExportFlags = u32;\n#[cfg(target_os = \"macos\")]\npub type SecKeyImportExportFlags = u32;\n\n#[cfg(target_os = \"macos\")]\npub const kSecKeyImportOnlyOne: SecKeyImportExportFlags = 1;\n#[cfg(target_os = \"macos\")]\npub const kSecKeySecurePassphrase: SecKeyImportExportFlags = 2;\n#[cfg(target_os = \"macos\")]\npub const kSecKeyNoAccessControl: SecKeyImportExportFlags = 4;\n\n#[cfg(target_os = \"macos\")]\npub const SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION: c_uint = 0;\n\n#[cfg(target_os = \"macos\")]\nmod sec_external_format {\n    use super::SecExternalFormat;\n    pub const kSecFormatUnknown: SecExternalFormat = 0;\n    /// a.k.a. X509 for public keys\n    pub const kSecFormatOpenSSL: SecExternalFormat = 1;\n    /// OpenSSH v.1\n    pub const kSecFormatSSH: SecExternalFormat = 2;\n    pub const kSecFormatBSAFE: SecExternalFormat = 3;\n    /// raw unformatted key bits\n    pub const kSecFormatRawKey: SecExternalFormat = 4;\n    pub const kSecFormatWrappedPKCS8: SecExternalFormat = 5;\n    /// traditional openssl\n    pub const kSecFormatWrappedOpenSSL: SecExternalFormat = 6;\n    /// OpenSSH v.1\n    pub const kSecFormatWrappedSSH: SecExternalFormat = 7;\n    pub const kSecFormatWrappedLSH: SecExternalFormat = 8;\n    /// DER encoded\n    pub const kSecFormatX509Cert: SecExternalFormat = 9;\n    /// sequence of certs and/or keys, implies PEM\n    pub const kSecFormatPEMSequence: SecExternalFormat = 10;\n    /// sequence of certs\n    pub const kSecFormatPKCS7: SecExternalFormat = 11;\n    /// set of certs and private keys\n    pub const kSecFormatPKCS12: SecExternalFormat = 12;\n    /// sequence of certs, form netscape-cert-sequence\n    pub const kSecFormatNetscapeCertSequence: SecExternalFormat = 13;\n    /// OpenSSH v.2\n    pub const kSecFormatSSHv2: SecExternalFormat = 14;\n}\n\n#[cfg(target_os = \"macos\")]\npub use sec_external_format::*;\n\n#[repr(C)]\n#[derive(Copy, Clone)]\n#[cfg(target_os = \"macos\")]\npub struct SecItemImportExportKeyParameters {\n    pub version: c_uint,\n    pub flags: SecKeyImportExportFlags,\n    pub passphrase: CFTypeRef,\n    pub alertTitle: CFStringRef,\n    pub alertPrompt: CFStringRef,\n    pub accessRef: SecAccessRef,\n    pub keyUsage: CFArrayRef,\n    pub keyAttributes: CFArrayRef,\n}\n\nextern \"C\" {\n    #[cfg(target_os = \"macos\")]\n    pub fn SecItemImport(\n        importedData: CFDataRef,\n        fileNameOrExtension: CFStringRef,\n        inputFormat: *mut SecExternalFormat,\n        itemType: *mut SecExternalItemType,\n        flags: SecItemImportExportFlags,\n        keyParams: *const SecItemImportExportKeyParameters,\n        importKeychain: SecKeychainRef,\n        outItems: *mut CFArrayRef,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn SecItemExport(\n        secItemOrArray: CFTypeRef,\n        outputFormat: SecExternalFormat,\n        flags: SecItemImportExportFlags,\n        keyParams: *const SecItemImportExportKeyParameters,\n        exportedData: *mut CFDataRef,\n    ) -> OSStatus;\n\n    pub static kSecImportExportPassphrase: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecImportExportKeychain: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecImportExportAccess: CFStringRef;\n\n    pub static kSecImportItemLabel: CFStringRef;\n    pub static kSecImportItemKeyID: CFStringRef;\n    pub static kSecImportItemTrust: CFStringRef;\n    pub static kSecImportItemCertChain: CFStringRef;\n    pub static kSecImportItemIdentity: CFStringRef;\n\n    pub fn SecPKCS12Import(\n        pkcs12_data: CFDataRef,\n        options: CFDictionaryRef,\n        items: *mut CFArrayRef,\n    ) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/item.rs",
    "content": "use core_foundation_sys::string::CFStringRef;\n\nextern \"C\" {\n    pub static kSecClass: CFStringRef;\n    pub static kSecClassInternetPassword: CFStringRef;\n    pub static kSecClassGenericPassword: CFStringRef;\n    pub static kSecClassCertificate: CFStringRef;\n    pub static kSecClassKey: CFStringRef;\n    pub static kSecClassIdentity: CFStringRef;\n\n    pub static kSecMatchLimit: CFStringRef;\n    pub static kSecMatchLimitAll: CFStringRef;\n\n    pub static kSecMatchTrustedOnly: CFStringRef;\n    pub static kSecMatchCaseInsensitive: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecMatchSubjectWholeString: CFStringRef;\n\n    pub static kSecReturnData: CFStringRef;\n    pub static kSecReturnAttributes: CFStringRef;\n    pub static kSecReturnRef: CFStringRef;\n    pub static kSecReturnPersistentRef: CFStringRef;\n\n    pub static kSecMatchSearchList: CFStringRef;\n\n    pub static kSecAttrApplicationLabel: CFStringRef;\n    pub static kSecAttrKeyType: CFStringRef;\n    pub static kSecAttrLabel: CFStringRef;\n    pub static kSecAttrIsPermanent: CFStringRef;\n    pub static kSecAttrPublicKeyHash: CFStringRef;\n    pub static kSecAttrSerialNumber: CFStringRef;\n    pub static kSecPrivateKeyAttrs: CFStringRef;\n    pub static kSecPublicKeyAttrs: CFStringRef;\n\n    pub static kSecAttrCanEncrypt: CFStringRef;\n    pub static kSecAttrCanDecrypt: CFStringRef;\n    pub static kSecAttrCanDerive: CFStringRef;\n    pub static kSecAttrCanWrap: CFStringRef;\n    pub static kSecAttrCanUnwrap: CFStringRef;\n    pub static kSecAttrCanSign: CFStringRef;\n    pub static kSecAttrCanVerify: CFStringRef;\n\n    pub static kSecAttrKeyClass: CFStringRef;\n    pub static kSecAttrKeyClassPublic: CFStringRef;\n    pub static kSecAttrKeyClassPrivate: CFStringRef;\n    pub static kSecAttrKeyClassSymmetric: CFStringRef;\n\n    #[cfg(target_os = \"macos\")]\n    pub static kSecUseKeychain: CFStringRef;\n    #[cfg(any(feature = \"OSX_10_15\", target_os = \"ios\", target_os = \"tvos\", target_os = \"watchos\", target_os = \"visionos\"))]\n    pub static kSecUseDataProtectionKeychain: CFStringRef;\n    pub static kSecAttrTokenID: CFStringRef;\n    pub static kSecAttrTokenIDSecureEnclave: CFStringRef;\n    pub static kSecUseAuthenticationContext: CFStringRef;\n    pub static kSecUseAuthenticationUI: CFStringRef;\n    pub static kSecUseAuthenticationUISkip: CFStringRef;\n    pub static kSecAttrSynchronizable: CFStringRef;\n    pub static kSecAttrSynchronizableAny: CFStringRef;\n\n    pub static kSecAttrKeySizeInBits: CFStringRef;\n\n    pub static kSecAttrKeyTypeECSECPrimeRandom: CFStringRef;\n    pub static kSecAttrKeyTypeRSA: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecAttrKeyTypeDSA: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecAttrKeyTypeAES: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecAttrKeyTypeDES: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecAttrKeyType3DES: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecAttrKeyTypeRC4: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecAttrKeyTypeRC2: CFStringRef;\n    #[cfg(target_os = \"macos\")]\n    pub static kSecAttrKeyTypeCAST: CFStringRef;\n    #[deprecated(note = \"Deprecated by Apple\")]\n    pub static kSecAttrKeyTypeEC: CFStringRef;\n\n    pub static kSecAttrAccessGroup: CFStringRef;\n    pub static kSecAttrAccessGroupToken: CFStringRef;\n\n    pub static kSecKeyKeyExchangeParameterRequestedSize: CFStringRef;\n    pub static kSecKeyKeyExchangeParameterSharedInfo: CFStringRef;\n\n    pub static kSecAttrAuthenticationType: CFStringRef;\n    pub static kSecAttrComment: CFStringRef;\n    pub static kSecAttrDescription: CFStringRef;\n    pub static kSecAttrPath: CFStringRef;\n    pub static kSecAttrPort: CFStringRef;\n    pub static kSecAttrProtocol: CFStringRef;\n    pub static kSecAttrSecurityDomain: CFStringRef;\n    pub static kSecAttrServer: CFStringRef;\n    pub static kSecAttrService: CFStringRef;\n    pub static kSecAttrAccessControl: CFStringRef;\n    pub static kSecAttrAccount: CFStringRef;\n    pub static kSecValueData: CFStringRef;\n    pub static kSecValueRef: CFStringRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/key.rs",
    "content": "use core_foundation_sys::base::CFTypeID;\nuse core_foundation_sys::data::CFDataRef;\nuse core_foundation_sys::dictionary::CFDictionaryRef;\nuse core_foundation_sys::error::CFErrorRef;\nuse core_foundation_sys::string::CFStringRef;\n\nuse crate::base::SecKeyRef;\n\npub type SecKeyAlgorithm = CFStringRef;\n\npub type SecKeyOperationType = u32;\npub const kSecKeyOperationTypeSign: SecKeyOperationType = 0;\npub const kSecKeyOperationTypeVerify: SecKeyOperationType = 1;\npub const kSecKeyOperationTypeEncrypt: SecKeyOperationType = 2;\npub const kSecKeyOperationTypeDecrypt: SecKeyOperationType = 3;\npub const kSecKeyOperationTypeKeyExchange: SecKeyOperationType = 4;\n\nextern \"C\" {\n    pub fn SecKeyGetTypeID() -> CFTypeID;\n\n    pub fn SecKeyCreateRandomKey(parameters: CFDictionaryRef, error: *mut CFErrorRef) -> SecKeyRef;\n\n    pub fn SecKeyCreateWithData(\n        keyData: CFDataRef,\n        attributes: CFDictionaryRef,\n        error: *mut CFErrorRef,\n    ) -> SecKeyRef;\n\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. There's no replacement for symmetric keys\")]\n    pub fn SecKeyCreateFromData(\n        parameters: CFDictionaryRef,\n        keyData: CFDataRef,\n        error: *mut CFErrorRef,\n    ) -> SecKeyRef;\n\n\n    pub fn SecKeyCopyExternalRepresentation(key: SecKeyRef, error: *mut CFErrorRef) -> CFDataRef;\n\n    pub fn SecKeyCopyAttributes(key: SecKeyRef) -> CFDictionaryRef;\n\n    pub fn SecKeyCopyPublicKey(key: SecKeyRef) -> SecKeyRef;\n\n\n    pub fn SecKeyCreateSignature(\n        key: SecKeyRef,\n        algorithm: SecKeyAlgorithm,\n        dataToSign: CFDataRef,\n        error: *mut CFErrorRef,\n    ) -> CFDataRef;\n\n\n    pub fn SecKeyVerifySignature(\n        key: SecKeyRef,\n        algorithm: SecKeyAlgorithm,\n        signedData: CFDataRef,\n        signature: CFDataRef,\n        error: *mut CFErrorRef,\n    ) -> core_foundation_sys::base::Boolean;\n\n\n    pub fn SecKeyCreateEncryptedData(\n        key: SecKeyRef,\n        algorithm: SecKeyAlgorithm,\n        plaintext: CFDataRef,\n        error: *mut CFErrorRef,\n    ) -> CFDataRef;\n\n\n    pub fn SecKeyCreateDecryptedData(\n        key: SecKeyRef,\n        algorithm: SecKeyAlgorithm,\n        ciphertext: CFDataRef,\n        error: *mut CFErrorRef,\n    ) -> CFDataRef;\n\n\n    pub fn SecKeyIsAlgorithmSupported(\n        key: SecKeyRef,\n        operation: SecKeyOperationType,\n        algorithm: SecKeyAlgorithm,\n    ) -> core_foundation_sys::base::Boolean;\n\n\n    pub fn SecKeyCopyKeyExchangeResult(\n        privateKey: SecKeyRef,\n        algorithm: SecKeyAlgorithm,\n        publicKey: SecKeyRef,\n        parameters: CFDictionaryRef,\n        error: *mut CFErrorRef,\n    ) -> CFDataRef;\n}\n\nmacro_rules! names {\n    ($( $(# $meta:literal )* $i:ident => $x:ident),*) => {\n        extern \"C\" {\n            $($(#[cfg(feature = $meta)])* pub static $x: SecKeyAlgorithm;)*\n        }\n\n        #[non_exhaustive]\n        #[derive(Copy, Clone)]\n        pub enum Algorithm {\n            $( $(#[cfg(feature = $meta)])* $i, )*\n        }\n\n        impl From<Algorithm> for SecKeyAlgorithm {\n            fn from(m: Algorithm) -> Self {\n                unsafe { match m {\n                    $( $(#[cfg(feature = $meta)])* Algorithm::$i => $x, )*\n                } }\n            }\n        }\n    }\n}\n\nnames! {\n    ECIESEncryptionStandardX963SHA1AESGCM => kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM,\n    ECIESEncryptionStandardX963SHA224AESGCM => kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM,\n    ECIESEncryptionStandardX963SHA256AESGCM => kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM,\n    ECIESEncryptionStandardX963SHA384AESGCM => kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM,\n    ECIESEncryptionStandardX963SHA512AESGCM => kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM,\n\n    ECIESEncryptionStandardVariableIVX963SHA224AESGCM => kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA224AESGCM,\n    ECIESEncryptionStandardVariableIVX963SHA256AESGCM => kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA256AESGCM,\n    ECIESEncryptionStandardVariableIVX963SHA384AESGCM => kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA384AESGCM,\n    ECIESEncryptionStandardVariableIVX963SHA512AESGCM => kSecKeyAlgorithmECIESEncryptionStandardVariableIVX963SHA512AESGCM,\n\n    ECIESEncryptionCofactorVariableIVX963SHA224AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA224AESGCM,\n    ECIESEncryptionCofactorVariableIVX963SHA256AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA256AESGCM,\n    ECIESEncryptionCofactorVariableIVX963SHA384AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA384AESGCM,\n    ECIESEncryptionCofactorVariableIVX963SHA512AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorVariableIVX963SHA512AESGCM,\n\n    ECIESEncryptionCofactorX963SHA1AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM,\n    ECIESEncryptionCofactorX963SHA224AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM,\n    ECIESEncryptionCofactorX963SHA256AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM,\n    ECIESEncryptionCofactorX963SHA384AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM,\n    ECIESEncryptionCofactorX963SHA512AESGCM => kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM,\n\n    ECDSASignatureRFC4754 => kSecKeyAlgorithmECDSASignatureRFC4754,\n\n    ECDSASignatureDigestX962 => kSecKeyAlgorithmECDSASignatureDigestX962,\n    ECDSASignatureDigestX962SHA1 => kSecKeyAlgorithmECDSASignatureDigestX962SHA1,\n    ECDSASignatureDigestX962SHA224 => kSecKeyAlgorithmECDSASignatureDigestX962SHA224,\n    ECDSASignatureDigestX962SHA256 => kSecKeyAlgorithmECDSASignatureDigestX962SHA256,\n    ECDSASignatureDigestX962SHA384 => kSecKeyAlgorithmECDSASignatureDigestX962SHA384,\n    ECDSASignatureDigestX962SHA512 => kSecKeyAlgorithmECDSASignatureDigestX962SHA512,\n\n    ECDSASignatureMessageX962SHA1 => kSecKeyAlgorithmECDSASignatureMessageX962SHA1,\n    ECDSASignatureMessageX962SHA224 => kSecKeyAlgorithmECDSASignatureMessageX962SHA224,\n    ECDSASignatureMessageX962SHA256 => kSecKeyAlgorithmECDSASignatureMessageX962SHA256,\n    ECDSASignatureMessageX962SHA384 => kSecKeyAlgorithmECDSASignatureMessageX962SHA384,\n    ECDSASignatureMessageX962SHA512 => kSecKeyAlgorithmECDSASignatureMessageX962SHA512,\n\n    ECDHKeyExchangeCofactor => kSecKeyAlgorithmECDHKeyExchangeCofactor,\n    ECDHKeyExchangeStandard => kSecKeyAlgorithmECDHKeyExchangeStandard,\n    ECDHKeyExchangeCofactorX963SHA1 => kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1,\n    ECDHKeyExchangeStandardX963SHA1 => kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1,\n    ECDHKeyExchangeCofactorX963SHA224 => kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224,\n    ECDHKeyExchangeCofactorX963SHA256 => kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256,\n    ECDHKeyExchangeCofactorX963SHA384 => kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384,\n    ECDHKeyExchangeCofactorX963SHA512 => kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512,\n    ECDHKeyExchangeStandardX963SHA224 => kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224,\n    ECDHKeyExchangeStandardX963SHA256 => kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256,\n    ECDHKeyExchangeStandardX963SHA384 => kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384,\n    ECDHKeyExchangeStandardX963SHA512 => kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512,\n\n    RSAEncryptionRaw => kSecKeyAlgorithmRSAEncryptionRaw,\n    RSAEncryptionPKCS1 => kSecKeyAlgorithmRSAEncryptionPKCS1,\n\n    RSAEncryptionOAEPSHA1 => kSecKeyAlgorithmRSAEncryptionOAEPSHA1,\n    RSAEncryptionOAEPSHA224 => kSecKeyAlgorithmRSAEncryptionOAEPSHA224,\n    RSAEncryptionOAEPSHA256 => kSecKeyAlgorithmRSAEncryptionOAEPSHA256,\n    RSAEncryptionOAEPSHA384 => kSecKeyAlgorithmRSAEncryptionOAEPSHA384,\n    RSAEncryptionOAEPSHA512 => kSecKeyAlgorithmRSAEncryptionOAEPSHA512,\n\n    RSAEncryptionOAEPSHA1AESGCM => kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM,\n    RSAEncryptionOAEPSHA224AESGCM => kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM,\n    RSAEncryptionOAEPSHA256AESGCM => kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM,\n    RSAEncryptionOAEPSHA384AESGCM => kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM,\n    RSAEncryptionOAEPSHA512AESGCM => kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM,\n\n    RSASignatureRaw => kSecKeyAlgorithmRSASignatureRaw,\n\n    RSASignatureDigestPKCS1v15Raw => kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw,\n    RSASignatureDigestPKCS1v15SHA1 => kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1,\n    RSASignatureDigestPKCS1v15SHA224 => kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224,\n    RSASignatureDigestPKCS1v15SHA256 => kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,\n    RSASignatureDigestPKCS1v15SHA384 => kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384,\n    RSASignatureDigestPKCS1v15SHA512 => kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512,\n\n    RSASignatureMessagePKCS1v15SHA1 => kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1,\n    RSASignatureMessagePKCS1v15SHA224 => kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224,\n    RSASignatureMessagePKCS1v15SHA256 => kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256,\n    RSASignatureMessagePKCS1v15SHA384 => kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384,\n    RSASignatureMessagePKCS1v15SHA512 => kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512,\n\n    RSASignatureDigestPSSSHA1 => kSecKeyAlgorithmRSASignatureDigestPSSSHA1,\n    RSASignatureDigestPSSSHA224 => kSecKeyAlgorithmRSASignatureDigestPSSSHA224,\n    RSASignatureDigestPSSSHA256 => kSecKeyAlgorithmRSASignatureDigestPSSSHA256,\n    RSASignatureDigestPSSSHA384 => kSecKeyAlgorithmRSASignatureDigestPSSSHA384,\n    RSASignatureDigestPSSSHA512 => kSecKeyAlgorithmRSASignatureDigestPSSSHA512,\n\n    RSASignatureMessagePSSSHA1 => kSecKeyAlgorithmRSASignatureMessagePSSSHA1,\n    RSASignatureMessagePSSSHA224 => kSecKeyAlgorithmRSASignatureMessagePSSSHA224,\n    RSASignatureMessagePSSSHA256 => kSecKeyAlgorithmRSASignatureMessagePSSSHA256,\n    RSASignatureMessagePSSSHA384 => kSecKeyAlgorithmRSASignatureMessagePSSSHA384,\n    RSASignatureMessagePSSSHA512 => kSecKeyAlgorithmRSASignatureMessagePSSSHA512\n}\n"
  },
  {
    "path": "security-framework-sys/src/keychain.rs",
    "content": "#[cfg(target_os = \"macos\")]\nuse core_foundation_sys::base::CFTypeRef;\n#[cfg(target_os = \"macos\")]\nuse core_foundation_sys::base::{Boolean, CFTypeID, OSStatus};\n#[cfg(target_os = \"macos\")]\nuse std::os::raw::{c_char, c_uint, c_void};\n\n#[cfg(target_os = \"macos\")]\nuse crate::base::SecKeychainItemRef;\n#[cfg(target_os = \"macos\")]\nuse crate::base::{SecAccessRef, SecKeychainRef};\n\n#[cfg(target_os = \"macos\")]\npub const SEC_KEYCHAIN_SETTINGS_VERS1: c_uint = 1;\n\n#[repr(C)]\n#[cfg(target_os = \"macos\")]\npub struct SecKeychainSettings {\n    pub version: c_uint,\n    pub lockOnSleep: Boolean,\n    pub useLockInterval: Boolean,\n    pub lockInterval: c_uint,\n}\n\n/// Like Apple's headers, it assumes Little Endian,\n/// as there are no supported Big Endian machines any more :(\nmacro_rules! char_lit {\n    ($e:expr) => {\n        ($e[3] as u32) + (($e[2] as u32) << 8) + (($e[1] as u32) << 16) + (($e[0] as u32) << 24)\n    };\n}\n\nmacro_rules! char_lit_swapped {\n    ($e:expr) => {\n        ($e[0] as u32) + (($e[1] as u32) << 8) + (($e[2] as u32) << 16) + (($e[3] as u32) << 24)\n    };\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\n#[allow(clippy::upper_case_acronyms)]\npub enum SecProtocolType {\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    FTP = char_lit!(b\"ftp \"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    FTPAccount = char_lit!(b\"ftpa\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    HTTP = char_lit!(b\"http\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    IRC = char_lit!(b\"irc \"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    NNTP = char_lit!(b\"nntp\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    POP3 = char_lit!(b\"pop3\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    SMTP = char_lit!(b\"smtp\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    SOCKS = char_lit!(b\"sox \"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    IMAP = char_lit!(b\"imap\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    LDAP = char_lit!(b\"ldap\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    AppleTalk = char_lit!(b\"atlk\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    AFP = char_lit!(b\"afp \"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    Telnet = char_lit!(b\"teln\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    SSH = char_lit!(b\"ssh \"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    FTPS = char_lit!(b\"ftps\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    HTTPS = char_lit!(b\"htps\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    HTTPProxy = char_lit!(b\"htpx\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    HTTPSProxy = char_lit!(b\"htsx\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    FTPProxy = char_lit!(b\"ftpx\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    CIFS = char_lit!(b\"cifs\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    SMB = char_lit!(b\"smb \"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    RTSP = char_lit!(b\"rtsp\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    RTSPProxy = char_lit!(b\"rtsx\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    DAAP = char_lit!(b\"daap\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    EPPC = char_lit!(b\"eppc\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    IPP = char_lit!(b\"ipp \"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    NNTPS = char_lit!(b\"ntps\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    LDAPS = char_lit!(b\"ldps\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    TelnetS = char_lit!(b\"tels\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    IMAPS = char_lit!(b\"imps\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    IRCS = char_lit!(b\"ircs\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    POP3S = char_lit!(b\"pops\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    CVSpserver = char_lit!(b\"cvsp\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    SVN = char_lit!(b\"svn \"),\n    Any = 0,\n}\n\n#[repr(u32)]\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\n#[allow(clippy::upper_case_acronyms)]\npub enum SecAuthenticationType {\n    // [sic] Apple has got two related enums each with a different endianness!\n    NTLM = char_lit_swapped!(b\"ntlm\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    MSN = char_lit_swapped!(b\"msna\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    DPA = char_lit_swapped!(b\"dpaa\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    RPA = char_lit_swapped!(b\"rpaa\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    HTTPBasic = char_lit_swapped!(b\"http\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    HTTPDigest = char_lit_swapped!(b\"httd\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    HTMLForm = char_lit_swapped!(b\"form\"),\n    #[cfg_attr(not(target_os = \"macos\"), deprecated(note = \"macOS only\"))]\n    Default = char_lit_swapped!(b\"dflt\"),\n    Any = 0,\n}\n\n#[repr(i32)]\n#[derive(Copy, Clone, Eq, PartialEq, Debug)]\npub enum SecPreferencesDomain {\n    User = 0,\n    System = 1,\n    Common = 2,\n    Dynamic = 3,\n}\n\nextern \"C\" {\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainGetTypeID() -> CFTypeID;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainCopyDefault(keychain: *mut SecKeychainRef) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainCopyDomainDefault(\n        domain: SecPreferencesDomain,\n        keychain: *mut SecKeychainRef,\n    ) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecKeychainCreate(\n        pathName: *const c_char,\n        passwordLength: c_uint,\n        password: *const c_void,\n        promptUser: Boolean,\n        initialAccess: SecAccessRef,\n        keychain: *mut SecKeychainRef,\n    ) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecKeychainOpen(pathName: *const c_char, keychain: *mut SecKeychainRef) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecKeychainUnlock(\n        keychain: SecKeychainRef,\n        passwordLength: c_uint,\n        password: *const c_void,\n        usePassword: Boolean,\n    ) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainFindGenericPassword(\n        keychainOrArray: CFTypeRef,\n        serviceNameLength: u32,\n        serviceName: *const c_char,\n        accountNameLength: u32,\n        accountName: *const c_char,\n        passwordLength: *mut u32,\n        passwordData: *mut *mut c_void,\n        itemRef: *mut SecKeychainItemRef,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainFindInternetPassword(\n        keychainOrArray: CFTypeRef,\n        serverNameLength: u32,\n        serverName: *const c_char,\n        securityDomainLength: u32,\n        securityDomain: *const c_char,\n        accountNameLength: u32,\n        accountName: *const c_char,\n        pathLength: u32,\n        path: *const c_char,\n        port: u16,\n        protocol: SecProtocolType,\n        authenticationType: SecAuthenticationType,\n        passwordLength: *mut u32,\n        passwordData: *mut *mut c_void,\n        itemRef: *mut SecKeychainItemRef,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainAddGenericPassword(\n        keychain: SecKeychainRef,\n        serviceNameLength: u32,\n        serviceName: *const c_char,\n        accountNameLength: u32,\n        accountName: *const c_char,\n        passwordLength: u32,\n        passwordData: *const c_void,\n        itemRef: *mut SecKeychainItemRef,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainAddInternetPassword(\n        keychain: SecKeychainRef,\n        serverNameLength: u32,\n        serverName: *const c_char,\n        securityDomainLength: u32,\n        securityDomain: *const c_char,\n        accountNameLength: u32,\n        accountName: *const c_char,\n        pathLength: u32,\n        path: *const c_char,\n        port: u16,\n        protocol: SecProtocolType,\n        authenticationType: SecAuthenticationType,\n        passwordLength: u32,\n        passwordData: *const c_void,\n        itemRef: *mut SecKeychainItemRef,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainSetSettings(\n        keychain: SecKeychainRef,\n        newSettings: *const SecKeychainSettings,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainGetUserInteractionAllowed(state: *mut Boolean) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    pub fn SecKeychainSetUserInteractionAllowed(state: Boolean) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/keychain_item.rs",
    "content": "#[cfg(target_os = \"macos\")]\nuse crate::base::{SecKeychainAttributeList, SecKeychainItemRef};\n#[cfg(target_os = \"macos\")]\nuse core_foundation_sys::base::CFTypeID;\nuse core_foundation_sys::base::{CFTypeRef, OSStatus};\nuse core_foundation_sys::dictionary::CFDictionaryRef;\n#[cfg(target_os = \"macos\")]\nuse std::os::raw::c_void;\n\nextern \"C\" {\n\n    /// Returns the unique identifier of the opaque type to which a keychain item object belongs.\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecKeychainItemGetTypeID() -> CFTypeID;\n\n    /// Adds one or more items to a keychain.\n    pub fn SecItemAdd(attributes: CFDictionaryRef, result: *mut CFTypeRef) -> OSStatus;\n\n    /// Returns one or more keychain items that match a search query, or copies attributes of specific keychain items.\n    pub fn SecItemCopyMatching(query: CFDictionaryRef, result: *mut CFTypeRef) -> OSStatus;\n\n    /// Modifies items that match a search query.\n    pub fn SecItemUpdate(query: CFDictionaryRef, attributesToUpdate: CFDictionaryRef) -> OSStatus;\n\n    /// Deletes items that match a search query.\n    pub fn SecItemDelete(query: CFDictionaryRef) -> OSStatus;\n\n    /// # Legacy API\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecKeychainItemModifyAttributesAndData(\n        itemRef: SecKeychainItemRef,\n        attrList: *const SecKeychainAttributeList,\n        length: u32,\n        data: *const c_void,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecKeychainItemFreeContent(\n        attrList: *mut SecKeychainAttributeList,\n        data: *mut c_void,\n    ) -> OSStatus;\n\n    #[cfg(target_os = \"macos\")]\n    #[deprecated(note = \"Deprecated by Apple. SecKeychain is deprecated\")]\n    pub fn SecKeychainItemDelete(itemRef: SecKeychainItemRef) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/lib.rs",
    "content": "#![allow(bad_style)]\n\n#[cfg_attr(target_vendor = \"apple\", link(name = \"Security\", kind = \"framework\"))]\nextern \"C\" {}\n\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod access;\npub mod access_control;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod authorization;\npub mod base;\npub mod certificate;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod certificate_oids;\npub mod cipher_suite;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod cms;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod code_signing;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod digest_transform;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod encrypt_transform;\npub mod identity;\npub mod import_export;\npub mod item;\npub mod key;\n/// macOS only\npub mod keychain;\npub mod keychain_item;\npub mod policy;\npub mod random;\npub mod secure_transport;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod transform;\npub mod trust;\n/// macOS only\n#[cfg(target_os = \"macos\")]\npub mod trust_settings;\n"
  },
  {
    "path": "security-framework-sys/src/policy.rs",
    "content": "use core_foundation_sys::base::{Boolean, CFOptionFlags, CFTypeID};\nuse core_foundation_sys::string::CFStringRef;\n\nuse crate::base::SecPolicyRef;\n\nmod revocation_flags {\n    use super::CFOptionFlags;\n\n    pub const kSecRevocationOCSPMethod: CFOptionFlags = 1 << 0;\n    pub const kSecRevocationCRLMethod: CFOptionFlags = 1 << 1;\n    pub const kSecRevocationPreferCRL: CFOptionFlags = 1 << 2;\n    pub const kSecRevocationRequirePositiveResponse: CFOptionFlags = 1 << 3;\n    pub const kSecRevocationNetworkAccessDisabled: CFOptionFlags = 1 << 4;\n    pub const kSecRevocationUseAnyAvailableMethod: CFOptionFlags = kSecRevocationOCSPMethod | kSecRevocationCRLMethod;\n}\n\npub use revocation_flags::*;\n\nextern \"C\" {\n    pub fn SecPolicyCreateSSL(server: Boolean, hostname: CFStringRef) -> SecPolicyRef;\n    pub fn SecPolicyCreateRevocation(revocationFlags: CFOptionFlags) -> SecPolicyRef;\n    pub fn SecPolicyGetTypeID() -> CFTypeID;\n    pub fn SecPolicyCreateBasicX509() -> SecPolicyRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/random.rs",
    "content": "use std::os::raw::{c_int, c_void};\n\npub enum __SecRandom {}\npub type SecRandomRef = *const __SecRandom;\n\nextern \"C\" {\n    pub static kSecRandomDefault: SecRandomRef;\n\n    pub fn SecRandomCopyBytes(rnd: SecRandomRef, count: usize, bytes: *mut c_void) -> c_int;\n}\n"
  },
  {
    "path": "security-framework-sys/src/secure_transport.rs",
    "content": "use core_foundation_sys::array::CFArrayRef;\n#[cfg(target_os = \"macos\")]\nuse core_foundation_sys::base::CFTypeRef;\nuse core_foundation_sys::base::{Boolean, CFAllocatorRef, OSStatus};\nuse std::os::raw::{c_char, c_int, c_void};\n\nuse crate::cipher_suite::SSLCipherSuite;\nuse crate::trust::SecTrustRef;\n\npub enum SSLContext {}\npub type SSLContextRef = *mut SSLContext;\n\npub type SSLConnectionRef = *const c_void;\n\npub type SSLProtocol = c_int;\npub const kSSLProtocolUnknown: SSLProtocol = 0;\npub const kSSLProtocol3: SSLProtocol = 2;\npub const kTLSProtocol1: SSLProtocol = 4;\npub const kTLSProtocol11: SSLProtocol = 7;\npub const kTLSProtocol12: SSLProtocol = 8;\npub const kDTLSProtocol1: SSLProtocol = 9;\npub const kTLSProtocol13: SSLProtocol = 10;\npub const kSSLProtocol2: SSLProtocol = 1;\npub const kSSLProtocol3Only: SSLProtocol = 3;\npub const kTLSProtocol1Only: SSLProtocol = 5;\npub const kSSLProtocolAll: SSLProtocol = 6;\n\npub type SSLSessionOption = c_int;\n#[deprecated(note = \"deprecated by Apple\")]\npub const kSSLSessionOptionBreakOnServerAuth: SSLSessionOption = 0;\n#[deprecated(note = \"deprecated by Apple\")]\npub const kSSLSessionOptionBreakOnCertRequested: SSLSessionOption = 1;\n#[deprecated(note = \"deprecated by Apple\")]\npub const kSSLSessionOptionBreakOnClientAuth: SSLSessionOption = 2;\n#[deprecated(note = \"deprecated by Apple\")]\npub const kSSLSessionOptionFalseStart: SSLSessionOption = 3;\npub const kSSLSessionOptionSendOneByteRecord: SSLSessionOption = 4;\n#[deprecated(note = \"deprecated by Apple\")]\npub const kSSLSessionOptionAllowServerIdentityChange: SSLSessionOption = 5;\n#[cfg(target_os = \"macos\")]\n#[deprecated(note = \"deprecated by Apple\")]\npub const kSSLSessionOptionFallback: SSLSessionOption = 6;\n#[deprecated(note = \"deprecated by Apple\")]\npub const kSSLSessionOptionBreakOnClientHello: SSLSessionOption = 7;\n\npub type SSLSessionState = c_int;\npub const kSSLIdle: SSLSessionState = 0;\npub const kSSLHandshake: SSLSessionState = 1;\npub const kSSLConnected: SSLSessionState = 2;\npub const kSSLClosed: SSLSessionState = 3;\npub const kSSLAborted: SSLSessionState = 4;\n\npub type SSLReadFunc = unsafe extern \"C\" fn(\n    connection: SSLConnectionRef,\n    data: *mut c_void,\n    dataLength: *mut usize,\n) -> OSStatus;\n\npub type SSLWriteFunc = unsafe extern \"C\" fn(\n    connection: SSLConnectionRef,\n    data: *const c_void,\n    dataLength: *mut usize,\n) -> OSStatus;\n\npub type SSLProtocolSide = c_int;\npub const kSSLServerSide: SSLProtocolSide = 0;\npub const kSSLClientSide: SSLProtocolSide = 1;\n\npub type SSLConnectionType = c_int;\npub const kSSLStreamType: SSLConnectionType = 0;\npub const kSSLDatagramType: SSLConnectionType = 1;\n\npub const errSSLProtocol: OSStatus = -9800;\npub const errSSLNegotiation: OSStatus = -9801;\npub const errSSLFatalAlert: OSStatus = -9802;\npub const errSSLWouldBlock: OSStatus = -9803;\npub const errSSLSessionNotFound: OSStatus = -9804;\npub const errSSLClosedGraceful: OSStatus = -9805;\npub const errSSLClosedAbort: OSStatus = -9806;\npub const errSSLXCertChainInvalid: OSStatus = -9807;\npub const errSSLBadCert: OSStatus = -9808;\npub const errSSLCrypto: OSStatus = -9809;\npub const errSSLInternal: OSStatus = -9810;\npub const errSSLModuleAttach: OSStatus = -9811;\npub const errSSLUnknownRootCert: OSStatus = -9812;\npub const errSSLNoRootCert: OSStatus = -9813;\npub const errSSLCertExpired: OSStatus = -9814;\npub const errSSLCertNotYetValid: OSStatus = -9815;\npub const errSSLClosedNoNotify: OSStatus = -9816;\npub const errSSLBufferOverflow: OSStatus = -9817;\npub const errSSLBadCipherSuite: OSStatus = -9818;\npub const errSSLPeerUnexpectedMsg: OSStatus = -9819;\npub const errSSLPeerBadRecordMac: OSStatus = -9820;\npub const errSSLPeerDecryptionFail: OSStatus = -9821;\npub const errSSLPeerRecordOverflow: OSStatus = -9822;\npub const errSSLPeerDecompressFail: OSStatus = -9823;\npub const errSSLPeerHandshakeFail: OSStatus = -9824;\npub const errSSLPeerBadCert: OSStatus = -9825;\npub const errSSLPeerUnsupportedCert: OSStatus = -9826;\npub const errSSLPeerCertRevoked: OSStatus = -9827;\npub const errSSLPeerCertExpired: OSStatus = -9828;\npub const errSSLPeerCertUnknown: OSStatus = -9829;\npub const errSSLIllegalParam: OSStatus = -9830;\npub const errSSLPeerUnknownCA: OSStatus = -9831;\npub const errSSLPeerAccessDenied: OSStatus = -9832;\npub const errSSLPeerDecodeError: OSStatus = -9833;\npub const errSSLPeerDecryptError: OSStatus = -9834;\npub const errSSLPeerExportRestriction: OSStatus = -9835;\npub const errSSLPeerProtocolVersion: OSStatus = -9836;\npub const errSSLPeerInsufficientSecurity: OSStatus = -9837;\npub const errSSLPeerInternalError: OSStatus = -9838;\npub const errSSLPeerUserCancelled: OSStatus = -9839;\npub const errSSLPeerNoRenegotiation: OSStatus = -9840;\npub const errSSLPeerAuthCompleted: OSStatus = -9841;\npub const errSSLClientCertRequested: OSStatus = -9842;\npub const errSSLHostNameMismatch: OSStatus = -9843;\npub const errSSLConnectionRefused: OSStatus = -9844;\npub const errSSLDecryptionFail: OSStatus = -9845;\npub const errSSLBadRecordMac: OSStatus = -9846;\npub const errSSLRecordOverflow: OSStatus = -9847;\npub const errSSLBadConfiguration: OSStatus = -9848;\npub const errSSLClientHelloReceived: OSStatus = -9851;\n\npub type SSLAuthenticate = c_int;\npub const kNeverAuthenticate: SSLAuthenticate = 0;\npub const kAlwaysAuthenticate: SSLAuthenticate = 1;\npub const kTryAuthenticate: SSLAuthenticate = 2;\n\npub type SSLClientCertificateState = c_int;\npub const kSSLClientCertNone: SSLClientCertificateState = 0;\npub const kSSLClientCertRequested: SSLClientCertificateState = 1;\npub const kSSLClientCertSent: SSLClientCertificateState = 2;\npub const kSSLClientCertRejected: SSLClientCertificateState = 3;\n\nextern \"C\" {\n    pub fn SSLContextGetTypeID() -> ::core_foundation_sys::base::CFTypeID;\n    pub fn SSLCreateContext(\n        alloc: CFAllocatorRef,\n        protocolSide: SSLProtocolSide,\n        connectionType: SSLConnectionType,\n    ) -> SSLContextRef;\n    #[cfg(target_os = \"macos\")]\n    pub fn SSLNewContext(isServer: Boolean, contextPtr: *mut SSLContextRef) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SSLDisposeContext(context: SSLContextRef) -> OSStatus;\n    pub fn SSLSetConnection(context: SSLContextRef, connection: SSLConnectionRef) -> OSStatus;\n    pub fn SSLGetConnection(context: SSLContextRef, connection: *mut SSLConnectionRef) -> OSStatus;\n    pub fn SSLSetIOFuncs(\n        context: SSLContextRef,\n        read: SSLReadFunc,\n        write: SSLWriteFunc,\n    ) -> OSStatus;\n    pub fn SSLHandshake(context: SSLContextRef) -> OSStatus;\n    pub fn SSLClose(context: SSLContextRef) -> OSStatus;\n    pub fn SSLRead(\n        context: SSLContextRef,\n        data: *mut c_void,\n        dataLen: usize,\n        processed: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLWrite(\n        context: SSLContextRef,\n        data: *const c_void,\n        dataLen: usize,\n        processed: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLSetPeerDomainName(\n        context: SSLContextRef,\n        peerName: *const c_char,\n        peerNameLen: usize,\n    ) -> OSStatus;\n    pub fn SSLGetPeerDomainNameLength(context: SSLContextRef, peerNameLen: *mut usize) -> OSStatus;\n    pub fn SSLGetPeerDomainName(\n        context: SSLContextRef,\n        peerName: *mut c_char,\n        peerNameLen: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLSetCertificate(context: SSLContextRef, certRefs: CFArrayRef) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SSLSetCertificateAuthorities(\n        context: SSLContextRef,\n        certificateOrArray: CFTypeRef,\n        replaceExisting: Boolean,\n    ) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SSLCopyCertificateAuthorities(\n        context: SSLContextRef,\n        certificates: *mut CFArrayRef,\n    ) -> OSStatus;\n    pub fn SSLSetSessionOption(\n        context: SSLContextRef,\n        option: SSLSessionOption,\n        value: Boolean,\n    ) -> OSStatus;\n    pub fn SSLGetSessionOption(\n        context: SSLContextRef,\n        option: SSLSessionOption,\n        value: *mut Boolean,\n    ) -> OSStatus;\n    pub fn SSLCopyPeerTrust(context: SSLContextRef, trust: *mut SecTrustRef) -> OSStatus;\n    pub fn SSLGetSessionState(context: SSLContextRef, state: *mut SSLSessionState) -> OSStatus;\n    pub fn SSLGetSupportedCiphers(\n        context: SSLContextRef,\n        ciphers: *mut SSLCipherSuite,\n        numCiphers: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLGetNumberSupportedCiphers(\n        context: SSLContextRef,\n        numCiphers: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLGetEnabledCiphers(\n        context: SSLContextRef,\n        ciphers: *mut SSLCipherSuite,\n        numCiphers: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLGetNumberEnabledCiphers(context: SSLContextRef, numCiphers: *mut usize) -> OSStatus;\n    pub fn SSLSetEnabledCiphers(\n        context: SSLContextRef,\n        ciphers: *const SSLCipherSuite,\n        numCiphers: usize,\n    ) -> OSStatus;\n    pub fn SSLGetNegotiatedCipher(context: SSLContextRef, cipher: *mut SSLCipherSuite) -> OSStatus;\n    pub fn SSLSetClientSideAuthenticate(context: SSLContextRef, auth: SSLAuthenticate) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SSLSetDiffieHellmanParams(\n        context: SSLContextRef,\n        dhParams: *const c_void,\n        dhParamsLen: usize,\n    ) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SSLGetDiffieHellmanParams(\n        context: SSLContextRef,\n        dhParams: *mut *const c_void,\n        dhParamsLen: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLSetPeerID(\n        context: SSLContextRef,\n        peerID: *const c_void,\n        peerIDLen: usize,\n    ) -> OSStatus;\n    pub fn SSLGetPeerID(\n        context: SSLContextRef,\n        peerID: *mut *const c_void,\n        peerIDLen: *mut usize,\n    ) -> OSStatus;\n    pub fn SSLGetBufferedReadSize(context: SSLContextRef, bufSize: *mut usize) -> OSStatus;\n    pub fn SSLGetClientCertificateState(\n        context: SSLContextRef,\n        clientState: *mut SSLClientCertificateState,\n    ) -> OSStatus;\n    pub fn SSLGetNegotiatedProtocolVersion(\n        context: SSLContextRef,\n        protocol: *mut SSLProtocol,\n    ) -> OSStatus;\n    pub fn SSLGetProtocolVersionMax(\n        context: SSLContextRef,\n        maxVersion: *mut SSLProtocol,\n    ) -> OSStatus;\n    pub fn SSLGetProtocolVersionMin(\n        context: SSLContextRef,\n        minVersion: *mut SSLProtocol,\n    ) -> OSStatus;\n    pub fn SSLSetProtocolVersionMax(context: SSLContextRef, maxVersion: SSLProtocol) -> OSStatus;\n    pub fn SSLSetProtocolVersionMin(context: SSLContextRef, minVersion: SSLProtocol) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SSLSetProtocolVersionEnabled(\n        context: SSLContextRef,\n        protocol: SSLProtocol,\n        enable: Boolean,\n    ) -> OSStatus;\n    pub fn SSLSetALPNProtocols(context: SSLContextRef, protocols: CFArrayRef) -> OSStatus;\n    pub fn SSLCopyALPNProtocols(context: SSLContextRef, protocols: *mut CFArrayRef) -> OSStatus;\n    pub fn SSLSetSessionTicketsEnabled(context: SSLContextRef, enabled: Boolean) -> OSStatus;\n}\n"
  },
  {
    "path": "security-framework-sys/src/transform.rs",
    "content": "use core_foundation_sys::base::{Boolean, CFTypeID, CFTypeRef};\nuse core_foundation_sys::error::CFErrorRef;\nuse core_foundation_sys::string::CFStringRef;\n\npub type SecTransformRef = CFTypeRef;\n\nextern \"C\" {\n    pub static kSecTransformInputAttributeName: CFStringRef;\n\n    #[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\n    pub fn SecTransformGetTypeID() -> CFTypeID;\n\n    #[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\n    pub fn SecTransformSetAttribute(\n        transformRef: SecTransformRef,\n        key: CFStringRef,\n        value: CFTypeRef,\n        error: *mut CFErrorRef,\n    ) -> Boolean;\n\n    #[deprecated(note = \"Deprecated by Apple. SecTransform is no longer supported\")]\n    pub fn SecTransformExecute(\n        transformRef: SecTransformRef,\n        errorRef: *mut CFErrorRef,\n    ) -> CFTypeRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/trust.rs",
    "content": "use crate::base::{SecCertificateRef, SecKeyRef};\nuse core_foundation_sys::array::CFArrayRef;\nuse core_foundation_sys::base::{Boolean, CFIndex, CFTypeID, CFTypeRef, OSStatus};\nuse core_foundation_sys::date::CFDateRef;\nuse core_foundation_sys::error::CFErrorRef;\n\npub type SecTrustResultType = u32;\n\npub const kSecTrustResultInvalid: SecTrustResultType = 0;\npub const kSecTrustResultProceed: SecTrustResultType = 1;\npub const kSecTrustResultDeny: SecTrustResultType = 3;\npub const kSecTrustResultUnspecified: SecTrustResultType = 4;\npub const kSecTrustResultRecoverableTrustFailure: SecTrustResultType = 5;\npub const kSecTrustResultFatalTrustFailure: SecTrustResultType = 6;\npub const kSecTrustResultOtherError: SecTrustResultType = 7;\n\n#[cfg(target_os = \"macos\")]\nmod flags {\n    pub type SecTrustOptionFlags = u32;\n\n    pub const kSecTrustOptionAllowExpired: SecTrustOptionFlags = 0x0000_0001;\n    pub const kSecTrustOptionLeafIsCA: SecTrustOptionFlags = 0x0000_0002;\n    pub const kSecTrustOptionFetchIssuerFromNet: SecTrustOptionFlags = 0x0000_0004;\n    pub const kSecTrustOptionAllowExpiredRoot: SecTrustOptionFlags = 0x0000_0008;\n    pub const kSecTrustOptionRequireRevPerCert: SecTrustOptionFlags = 0x0000_0010;\n    pub const kSecTrustOptionUseTrustSettings: SecTrustOptionFlags = 0x0000_0020;\n    pub const kSecTrustOptionImplicitAnchors: SecTrustOptionFlags = 0x0000_0040;\n}\n\n#[cfg(target_os = \"macos\")]\npub use flags::*;\n\npub enum __SecTrust {}\n\npub type SecTrustRef = *mut __SecTrust;\n\nextern \"C\" {\n    pub fn SecTrustGetTypeID() -> CFTypeID;\n    #[cfg(any(feature = \"macos-12\", not(target_os = \"macos\")))]\n    pub fn SecTrustCopyCertificateChain(trust: SecTrustRef) -> CFArrayRef;\n    pub fn SecTrustGetCertificateCount(trust: SecTrustRef) -> CFIndex;\n    #[deprecated(note = \"deprecated by Apple, use SecTrustCopyCertificateChain\")]\n    pub fn SecTrustGetCertificateAtIndex(trust: SecTrustRef, ix: CFIndex) -> SecCertificateRef;\n    pub fn SecTrustSetVerifyDate(trust: SecTrustRef, verifyDate: CFDateRef) -> OSStatus;\n    pub fn SecTrustSetAnchorCertificates(trust: SecTrustRef, anchorCertificates: CFArrayRef) -> OSStatus;\n    pub fn SecTrustSetAnchorCertificatesOnly(trust: SecTrustRef, anchorCertificatesOnly: Boolean) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecTrustCopyAnchorCertificates(anchors: *mut CFArrayRef) -> OSStatus;\n    #[deprecated(note = \"deprecated by Apple\")]\n    pub fn SecTrustEvaluate(trust: SecTrustRef, result: *mut SecTrustResultType) -> OSStatus;\n    pub fn SecTrustEvaluateWithError(trust: SecTrustRef, error: *mut CFErrorRef) -> bool;\n    pub fn SecTrustCreateWithCertificates(\n        certificates: CFTypeRef,\n        policies: CFTypeRef,\n        trust: *mut SecTrustRef,\n    ) -> OSStatus;\n    pub fn SecTrustSetPolicies(trust: SecTrustRef, policies: CFTypeRef) -> OSStatus;\n    #[cfg(target_os = \"macos\")]\n    pub fn SecTrustSetOptions(trust: SecTrustRef, options: SecTrustOptionFlags) -> OSStatus;\n    pub fn SecTrustGetNetworkFetchAllowed(trust: SecTrustRef, allowFetch: *mut Boolean) -> OSStatus;\n    pub fn SecTrustSetNetworkFetchAllowed(trust: SecTrustRef, allowFetch: Boolean) -> OSStatus;\n    pub fn SecTrustSetOCSPResponse(trust: SecTrustRef, responseData: CFTypeRef) -> OSStatus;\n    pub fn SecTrustSetSignedCertificateTimestamps(\n        trust: SecTrustRef,\n        sctArray: CFArrayRef,\n    ) -> OSStatus;\n    pub fn SecTrustCopyPublicKey(trust: SecTrustRef) -> SecKeyRef;\n}\n"
  },
  {
    "path": "security-framework-sys/src/trust_settings.rs",
    "content": "use crate::base::SecCertificateRef;\nuse core_foundation_sys::array::CFArrayRef;\nuse core_foundation_sys::base::{CFTypeRef, OSStatus};\n\npub type SecTrustSettingsDomain = u32;\n\npub const kSecTrustSettingsDomainUser: SecTrustSettingsDomain = 0;\npub const kSecTrustSettingsDomainAdmin: SecTrustSettingsDomain = 1;\npub const kSecTrustSettingsDomainSystem: SecTrustSettingsDomain = 2;\n\npub type SecTrustSettingsResult = u32;\n\npub const kSecTrustSettingsResultInvalid: SecTrustSettingsResult = 0;\npub const kSecTrustSettingsResultTrustRoot: SecTrustSettingsResult = 1;\npub const kSecTrustSettingsResultTrustAsRoot: SecTrustSettingsResult = 2;\npub const kSecTrustSettingsResultDeny: SecTrustSettingsResult = 3;\npub const kSecTrustSettingsResultUnspecified: SecTrustSettingsResult = 4;\n\nextern \"C\" {\n    pub fn SecTrustSettingsCopyCertificates(\n        domain: SecTrustSettingsDomain,\n        certsOut: *mut CFArrayRef,\n    ) -> OSStatus;\n    pub fn SecTrustSettingsCopyTrustSettings(\n        certificateRef: SecCertificateRef,\n        domain: SecTrustSettingsDomain,\n        trustSettings: *mut CFArrayRef,\n    ) -> OSStatus;\n    pub fn SecTrustSettingsSetTrustSettings(\n        certificateRef: SecCertificateRef,\n        domain: SecTrustSettingsDomain,\n        trustSettingsDictOrArray: CFTypeRef,\n    ) -> OSStatus;\n}\n"
  },
  {
    "path": "systest/Cargo.toml",
    "content": "[package]\nname = \"systest\"\nversion = \"0.1.0\"\nauthors = [\"Steven Fackler <sfackler@palantir.com>\"]\nedition = \"2021\"\npublish = false\n\n[dependencies]\ncore-foundation-sys = \"0.8.7\"\nsecurity-framework-sys = { path = \"../security-framework-sys\" }\nlibc = \"0.2.182\"\n\n[build-dependencies]\nctest2 = \"0.4.8\"\n\n[package.metadata.release]\nrelease = false\n\n[lints.clippy]\nall = \"allow\"\n\n[lints.rust]\nmissing_abi = \"allow\"\n"
  },
  {
    "path": "systest/build.rs",
    "content": "use std::env;\n\nfn main() {\n    let mut test = ctest2::TestGenerator::new();\n\n    if env::var(\"TARGET\").unwrap().contains(\"darwin\") {\n        test.header(\"Security/SecAccess.h\")\n            .header(\"Security/SecAccessControl.h\")\n            .header(\"Security/SecDigestTransform.h\")\n            .header(\"Security/SecEncryptTransform.h\")\n            .header(\"Security/SecKeychain.h\")\n            .header(\"Security/SecKeychainItem.h\")\n            .header(\"Security/SecCertificateOIDs.h\")\n            .header(\"Security/SecTransform.h\")\n            .header(\"Security/SecTrustSettings.h\")\n            .header(\"Security/Authorization.h\")\n            .header(\"Security/AuthorizationDB.h\")\n            .header(\"Security/CMSEncoder.h\")\n            .header(\"Security/CMSDecoder.h\")\n            .header(\"Security/CodeSigning.h\");\n    }\n\n    test.header(\"Security/SecBase.h\")\n        .header(\"Security/SecCertificate.h\")\n        .header(\"Security/CipherSuite.h\")\n        .header(\"Security/SecIdentity.h\")\n        .header(\"Security/SecAccessControl.h\")\n        .header(\"Security/SecImportExport.h\")\n        .header(\"Security/SecItem.h\")\n        .header(\"Security/SecKey.h\")\n        .header(\"Security/SecPolicy.h\")\n        .header(\"Security/SecRandom.h\")\n        .header(\"Security/SecureTransport.h\")\n        .header(\"Security/SecTrust.h\")\n        .flag(\"-Wno-deprecated-declarations\")\n        .type_name(|name, _, _| name.to_string())\n        .skip_signededness(|s| s.ends_with(\"Ref\") || s.ends_with(\"Func\"))\n        .skip_fn(|s| s == \"SecRandomCopyBytes\") // varies between macOS versions\n        .generate(\"../security-framework-sys/src/lib.rs\", \"all.rs\");\n}\n"
  },
  {
    "path": "systest/src/main.rs",
    "content": "#![allow(bad_style)]\n#![allow(unused)]\n#![allow(clippy::all)]\n#![allow(deprecated)]\n#![allow(deref_nullptr)]\n#![allow(invalid_value)] // mem::uninitialized has to stay\n#![allow(clippy::all)]\n#![allow(function_casts_as_integer)]\n#![allow(deprecated)]\n\nuse core_foundation_sys::base::{CFOptionFlags, OSStatus};\nuse core_foundation_sys::string::CFStringRef;\nuse std::os::raw::*;\n\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::access::*;\nuse security_framework_sys::access_control::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::authorization::*;\nuse security_framework_sys::base::*;\nuse security_framework_sys::certificate::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::certificate_oids::*;\nuse security_framework_sys::cipher_suite::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::cms::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::code_signing::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::digest_transform::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::encrypt_transform::*;\nuse security_framework_sys::identity::*;\nuse security_framework_sys::import_export::*;\nuse security_framework_sys::item::*;\nuse security_framework_sys::key::*;\nuse security_framework_sys::keychain::*;\nuse security_framework_sys::keychain_item::*;\nuse security_framework_sys::policy::*;\nuse security_framework_sys::random::*;\nuse security_framework_sys::secure_transport::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::transform::*;\nuse security_framework_sys::trust::*;\n#[cfg(target_os = \"macos\")]\nuse security_framework_sys::trust_settings::*;\n\ninclude!(concat!(env!(\"OUT_DIR\"), \"/all.rs\"));\n"
  }
]