├── .cargo
└── audit.toml
├── .circleci
└── config.yml
├── .dockerignore
├── .github
├── CODEOWNERS
├── actions
│ ├── build_export_docker
│ │ └── action.yml
│ ├── ci_script
│ │ └── action.yml
│ └── load_docker
│ │ └── action.yml
└── workflows
│ ├── ci.yml
│ ├── nightly-next.yml
│ └── nightly.yml
├── .gitignore
├── .gitmodules
├── .travis.yml.disabled
├── CHANGELOG.md
├── CODE-OF-CONDUCT.md
├── CONTRIBUTORS.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── MAINTAINERS.toml
├── PARTNERS.md
├── README.md
├── SECURITY.md
├── build.rs
├── ci.sh
├── config.toml
├── deny.toml
├── doc
└── images
│ ├── parsec
│ ├── ARM1007_PARSEC Logo_ST2_RGB_Stacked_Colour.png
│ └── ParsecConceptDiagram.png
│ └── partners
│ ├── arm
│ └── Arm_logo_blue_150LG.png
│ ├── docker
│ └── vertical-logo-monochromatic.png
│ ├── linaro
│ └── Logo_linaro.png
│ ├── mirantis
│ └── mirantis-logo-2color-rgb-transparent.png
│ ├── nxp
│ └── NXP_logo_RGB_web.jpg
│ ├── rancher
│ └── rancher-logo-stacked-color.png
│ └── redhat
│ └── Logo-RedHat-D-Color-RGB.png
├── e2e_tests
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── docker_image
│ ├── _exec_wrapper
│ ├── cross-compile-tss.sh
│ ├── generate-keys.sh
│ ├── import-old-e2e-tests.sh
│ ├── parsec-service-test-all.Dockerfile
│ └── parsec-service-test-cross-compile.Dockerfile
├── fake_mappings
│ └── cGFyc2VjLXRvb2w=
│ │ ├── 1
│ │ └── dG90bw==
│ │ └── 2
│ │ └── dG90bw==
├── provider_cfg
│ ├── all
│ │ ├── config.toml
│ │ └── on-disk-kim-all-providers.toml
│ ├── cryptoauthlib
│ │ ├── cal_access_keys.toml
│ │ ├── config-sqlite.toml
│ │ ├── config.toml
│ │ ├── config_508a.toml
│ │ └── config_608a.toml
│ ├── mbed-crypto
│ │ ├── config-sqlite.toml
│ │ └── config.toml
│ ├── pkcs11
│ │ ├── config-sqlite.toml
│ │ └── config.toml
│ ├── tpm
│ │ ├── config-sqlite.toml
│ │ └── config.toml
│ └── trusted-service
│ │ ├── config-sqlite.toml
│ │ └── config.toml
├── src
│ ├── lib.rs
│ ├── raw_request.rs
│ └── stress.rs
└── tests
│ ├── all_providers
│ ├── config
│ │ ├── mod.rs
│ │ └── tomls
│ │ │ ├── allow_deprecated.toml
│ │ │ ├── allow_export.toml
│ │ │ ├── list_providers_1.toml
│ │ │ ├── list_providers_2.toml
│ │ │ ├── no_endorsement_auth.toml
│ │ │ ├── no_serial_or_slot_number.toml
│ │ │ ├── no_tpm_support.toml
│ │ │ ├── no_user_pin.toml
│ │ │ ├── pkcs11_pin_hex_fmt.toml
│ │ │ ├── pkcs11_pin_str_fmt_with_hex_word.toml
│ │ │ ├── pkcs11_software.toml
│ │ │ ├── reject_deprecated.toml
│ │ │ ├── serial_number_only.toml
│ │ │ ├── serial_number_padding.toml
│ │ │ ├── slot_number_only.toml
│ │ │ ├── slot_numbers_mismatch.toml
│ │ │ ├── ts_pkcs11_cross.toml
│ │ │ └── various_field_check.toml
│ ├── cross.rs
│ ├── logging.rs
│ ├── mod.rs
│ ├── multitenancy.rs
│ └── normal.rs
│ ├── mod.rs
│ └── per_provider
│ ├── key_mappings.rs
│ ├── mod.rs
│ ├── normal_tests
│ ├── aead.rs
│ ├── asym_encryption.rs
│ ├── asym_sign_verify.rs
│ ├── auth.rs
│ ├── basic.rs
│ ├── capability_discovery.rs
│ ├── cipher.rs
│ ├── create_destroy_key.rs
│ ├── export_key.rs
│ ├── export_public_key.rs
│ ├── generate_random.rs
│ ├── hash.rs
│ ├── import_key.rs
│ ├── key_agreement.rs
│ ├── key_attestation.rs
│ ├── key_attributes.rs
│ ├── mod.rs
│ └── ping.rs
│ ├── stress_test.rs
│ └── tpm_reset.rs
├── fuzz.sh
├── fuzz
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── build.rs
├── cleanup.sh
├── config.toml
├── fuzz_targets
│ └── fuzz_service.rs
└── run_fuzz.sh
├── quickstart
├── config.toml
├── construct-build-details.sh
├── docker_README.md
├── package.sh
├── quickstart.Dockerfile
└── tarball_README.md
├── src
├── authenticators
│ ├── direct_authenticator
│ │ └── mod.rs
│ ├── jwt_svid_authenticator
│ │ └── mod.rs
│ ├── mod.rs
│ └── unix_peer_credentials_authenticator
│ │ └── mod.rs
├── back
│ ├── backend_handler.rs
│ ├── dispatcher.rs
│ └── mod.rs
├── bin
│ └── main.rs
├── front
│ ├── domain_socket.rs
│ ├── front_end.rs
│ ├── listener.rs
│ └── mod.rs
├── key_info_managers
│ ├── mod.rs
│ ├── on_disk_manager
│ │ └── mod.rs
│ └── sqlite_manager
│ │ └── mod.rs
├── lib.rs
├── providers
│ ├── core
│ │ └── mod.rs
│ ├── crypto_capability.rs
│ ├── cryptoauthlib
│ │ ├── access_keys.rs
│ │ ├── aead.rs
│ │ ├── asym_sign.rs
│ │ ├── cipher.rs
│ │ ├── generate_random.rs
│ │ ├── hash.rs
│ │ ├── key_agreement.rs
│ │ ├── key_management.rs
│ │ ├── key_slot.rs
│ │ ├── key_slot_storage.rs
│ │ └── mod.rs
│ ├── mbed_crypto
│ │ ├── aead.rs
│ │ ├── asym_encryption.rs
│ │ ├── asym_sign.rs
│ │ ├── capability_discovery.rs
│ │ ├── generate_random.rs
│ │ ├── hash.rs
│ │ ├── key_agreement.rs
│ │ ├── key_management.rs
│ │ └── mod.rs
│ ├── mod.rs
│ ├── pkcs11
│ │ ├── asym_encryption.rs
│ │ ├── asym_sign.rs
│ │ ├── capability_discovery.rs
│ │ ├── generate_random.rs
│ │ ├── key_management.rs
│ │ ├── key_metadata.rs
│ │ ├── mod.rs
│ │ └── utils.rs
│ ├── tpm
│ │ ├── asym_encryption.rs
│ │ ├── asym_sign.rs
│ │ ├── capability_discovery.rs
│ │ ├── generate_random.rs
│ │ ├── key_attestation.rs
│ │ ├── key_management.rs
│ │ ├── mod.rs
│ │ └── utils.rs
│ └── trusted_service
│ │ ├── asym_encryption.rs
│ │ ├── asym_sign.rs
│ │ ├── capability_discovery.rs
│ │ ├── context
│ │ ├── asym_encryption.rs
│ │ ├── asym_sign.rs
│ │ ├── error.rs
│ │ ├── generate_random.rs
│ │ ├── key_management.rs
│ │ ├── mod.rs
│ │ └── ts_protobuf.rs
│ │ ├── error.rs
│ │ ├── generate_random.rs
│ │ ├── key_management.rs
│ │ └── mod.rs
└── utils
│ ├── cli.rs
│ ├── config.rs
│ ├── global_config.rs
│ ├── mod.rs
│ ├── service_builder.rs
│ └── tests
│ ├── config
│ ├── providers_different_type.toml
│ ├── providers_different_type_same_name.toml
│ ├── providers_same_type_default_name.toml
│ ├── providers_same_type_different_name.toml
│ └── providers_same_type_same_name.toml
│ └── mod.rs
├── systemd-daemon
└── parsec.service
├── test
├── cross-compile.sh
└── pkg-config
└── utils
├── dependency_cross_matcher.py
└── release_tracking.py
/.cargo/audit.toml:
--------------------------------------------------------------------------------
1 | [advisories]
2 | informational_warnings = ["unmaintained"] # warn for categories of informational advisories
3 | severity_threshold = "low" # CVSS severity ("none", "low", "medium", "high", "critical")
4 |
5 | # Advisory Database Configuration
6 | [database]
7 | path = "/tmp/advisory-db" # Path where advisory git repo will be cloned
8 | url = "https://github.com/RustSec/advisory-db.git" # URL to git repo
9 | fetch = true # Perform a `git fetch` before auditing
10 | stale = false # Allow stale advisory DB (i.e. no commits for 90 days)
11 |
12 | # Output Configuration
13 | [output]
14 | deny = ["unmaintained"] # exit on error if unmaintained dependencies are found
15 | format = "terminal" # "terminal" (human readable report) or "json"
16 | quiet = false # Only print information on error
17 | show_tree = true # Show inverse dependency trees along with advisories
18 |
19 | # Target Configuration
20 | [target]
21 | os = "linux" # Ignore advisories for operating systems other than this one
22 |
23 | [yanked]
24 | enabled = true # Warn for yanked crates in Cargo.lock
25 | update_index = true # Auto-update the crates.io index
26 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 | jobs:
3 | build:
4 | working_directory: ~/repo
5 | docker:
6 | - image: ghcr.io/parallaxsecond/parsec-service-test-all
7 | resource_class: arm.medium
8 | steps:
9 | - checkout
10 | - run: |
11 | git submodule update --init --recursive
12 | cargo build --features=all-providers,all-authenticators
13 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | quickstart/quickstart.Dockerfile
2 | quickstart/package.sh
3 | quickstart/*.tar.gz
4 | .idea/
5 |
6 | # Copied from .gitignore
7 | /target
8 | *.psa_its
9 | *.swp
10 | tags
11 | *DS_Store
12 | *vscode
13 | *.patch
14 | mappings/
15 | kim-mappings/
16 | NVChip
17 | .devcontainer
18 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # The content of the config.rs file should not change in a breaking way.
2 | # See https://github.com/parallaxsecond/parsec/issues/393 for details.
3 | src/utils/config.rs @parallaxsecond/admin
4 | # The content of the cli.rs file should not change in a breaking way.
5 | # See https://github.com/parallaxsecond/parsec/issues/392 for details.
6 | src/utils/cli.rs @parallaxsecond/admin
7 | # The Docker container is also used to check that there are no breaking
8 | # changes in buildtime dependencies.
9 | # See https://github.com/parallaxsecond/parsec/issues/397
10 | # See https://github.com/parallaxsecond/parsec/issues/408
11 | e2e_tests/docker_image/ @parallaxsecond/admin
12 | # The way tests are executed should be only modified carefully to not remove
13 | # regression or breaking changes detection.
14 | ci.sh @parallaxsecond/admin
15 | # The main function file contains interactions with the operating system which must
16 | # stay stable.
17 | src/bin/main.rs @parallaxsecond/admin
18 |
--------------------------------------------------------------------------------
/.github/actions/build_export_docker/action.yml:
--------------------------------------------------------------------------------
1 | name: "Build and export docker image"
2 | description: "Builds and exports the docker images required by Parsec CI"
3 | inputs:
4 | image-name:
5 | required: true
6 | description: "Docker image name"
7 |
8 | runs:
9 | using: "composite"
10 | steps:
11 | - name: Build the docker container
12 | run: pushd e2e_tests/docker_image && docker build -t ${{ inputs.image-name }} -f ${{ inputs.image-name }}.Dockerfile . && popd
13 | shell: bash
14 | - name: Export the docker container
15 | run: docker save ${{ inputs.image-name }} > /tmp/${{ inputs.image-name }}.tar
16 | shell: bash
17 | - name: Upload artifact
18 | uses: actions/upload-artifact@v3
19 | with:
20 | name: ${{ inputs.image-name }}
21 | path: /tmp/${{ inputs.image-name }}.tar
22 |
--------------------------------------------------------------------------------
/.github/actions/ci_script/action.yml:
--------------------------------------------------------------------------------
1 | name: "Run CI Tests"
2 | description: "Run the ci.sh script with the specified flags"
3 | inputs:
4 | ci-flags:
5 | required: true
6 | description: "Flags with which to run the ci.sh tests"
7 | rs-version:
8 | required: true
9 | default: "stable"
10 | description: "Rust version with which to run the tests"
11 |
12 | runs:
13 | using: "composite"
14 | steps:
15 | - name: Load Docker
16 | uses: ./.github/actions/load_docker
17 | if: ${{ env.TEST_ALL_DOCKER_IMAGE == 'parsec-service-test-all' }}
18 | with:
19 | image-name: "${{ env.TEST_ALL_DOCKER_IMAGE }}"
20 | image-path: "/tmp"
21 | - name: Run the container to execute the test script
22 | run: docker run -v $(pwd):/tmp/parsec -w /tmp/parsec --env RUST_TOOLCHAIN_VERSION=${{ inputs.rs-version }} -t ${{ env.TEST_ALL_DOCKER_IMAGE }} /tmp/parsec/ci.sh ${{ inputs.ci-flags }}
23 | shell: bash
24 |
--------------------------------------------------------------------------------
/.github/actions/load_docker/action.yml:
--------------------------------------------------------------------------------
1 | name: "Load docker image"
2 | description: "Load docker image"
3 | inputs:
4 | image-name:
5 | required: true
6 | description: "Docker image name"
7 | image-path:
8 | required: true
9 | description: "Path to save the docker image"
10 |
11 | runs:
12 | using: "composite"
13 | steps:
14 | - uses: actions/checkout@v3
15 | - name: Download artifact
16 | uses: actions/download-artifact@v3
17 | with:
18 | name: ${{ inputs.image-name }}
19 | path: ${{ inputs.image-path }}
20 | - name: Load image
21 | run: docker load --input ${{ inputs.image-path }}/${{ inputs.image-name }}.tar
22 | shell: bash
23 |
--------------------------------------------------------------------------------
/.github/workflows/nightly-next.yml:
--------------------------------------------------------------------------------
1 | name: Nightly Next Branch Checks
2 |
3 | on:
4 | schedule:
5 | # Every night at midnight
6 | - cron: "0 0 * * *"
7 | workflow_dispatch:
8 | inputs:
9 | rev:
10 | description: "Revision hash to run against"
11 | required: false
12 | default: ""
13 |
14 |
15 | env:
16 | TEST_ALL_DOCKER_IMAGE: 'ghcr.io/parallaxsecond/parsec-service-test-all'
17 |
18 | jobs:
19 | all-providers:
20 | name: Various tests targeting a Parsec image with all providers included
21 | runs-on: ubuntu-latest
22 | steps:
23 | - uses: actions/checkout@v3
24 | with:
25 | ref: "${{ github.event.inputs.rev }}"
26 | - name: Run the container to execute the test script
27 | uses: ./.github/actions/ci_script
28 | with:
29 | ci-flags: "all --test-next-branch-tracking"
30 |
31 | build-all-providers:
32 | name: Cargo check all-providers (current Rust stable & old compiler)
33 | runs-on: ubuntu-latest
34 | steps:
35 | - uses: actions/checkout@v3
36 | with:
37 | ref: "${{ github.event.inputs.rev }}"
38 | - name: Run the container to execute the test script
39 | uses: ./.github/actions/ci_script
40 | with:
41 | ci-flags: "cargo-check --test-next-branch-tracking"
42 |
43 | mbed-crypto-provider:
44 | name: Integration tests using Mbed Crypto provider
45 | runs-on: ubuntu-latest
46 | steps:
47 | - uses: actions/checkout@v3
48 | with:
49 | ref: "${{ github.event.inputs.rev }}"
50 | - name: Run the container to execute the test script
51 | uses: ./.github/actions/ci_script
52 | with:
53 | ci-flags: "mbed-crypto --test-next-branch-tracking"
54 |
55 | pkcs11-provider:
56 | name: Integration tests using PKCS 11 provider
57 | runs-on: ubuntu-latest
58 | steps:
59 | - uses: actions/checkout@v3
60 | with:
61 | ref: "${{ github.event.inputs.rev }}"
62 | - name: Run the container to execute the test script
63 | uses: ./.github/actions/ci_script
64 | with:
65 | ci-flags: "pkcs11 --no-stress-test --test-next-branch-tracking"
66 |
67 | tpm-provider:
68 | name: Integration tests using TPM provider
69 | runs-on: ubuntu-latest
70 | steps:
71 | - uses: actions/checkout@v3
72 | with:
73 | ref: "${{ github.event.inputs.rev }}"
74 | - name: Run the container to execute the test script
75 | uses: ./.github/actions/ci_script
76 | with:
77 | ci-flags: "tpm --test-next-branch-tracking"
78 |
79 | trusted-service-provider:
80 | name: Integration tests using Crypto Trusted Service provider
81 | runs-on: ubuntu-latest
82 | steps:
83 | - uses: actions/checkout@v3
84 | with:
85 | ref: "${{ github.event.inputs.rev }}"
86 | - name: Run the container to execute the test script
87 | uses: ./.github/actions/ci_script
88 | with:
89 | ci-flags: "trusted-service --test-next-branch-tracking"
90 |
--------------------------------------------------------------------------------
/.github/workflows/nightly.yml:
--------------------------------------------------------------------------------
1 | name: Nightly Checks
2 |
3 | on:
4 | schedule:
5 | # Every night at midnight
6 | - cron: "0 0 * * *"
7 | workflow_dispatch:
8 | inputs:
9 | rev:
10 | description: "Revision hash to run against"
11 | required: false
12 | default: ""
13 |
14 | jobs:
15 | dependencies:
16 | name: Check for unused dependencies
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v2
20 | with:
21 | ref: "${{ github.event.inputs.rev }}"
22 | - name: Install latest Rust
23 | uses: actions-rs/toolchain@v1
24 | with:
25 | toolchain: nightly
26 | - name: Install cargo udeps
27 | run: cargo install cargo-udeps --locked
28 | - name: Execute cargo udeps
29 | run: cargo +nightly udeps
30 |
31 | audit:
32 | name: Check for crates with security vulnerabilities
33 | runs-on: ubuntu-latest
34 | steps:
35 | - uses: actions/checkout@v2
36 | with:
37 | ref: "${{ github.event.inputs.rev }}"
38 | - name: Install latest Rust
39 | uses: actions-rs/toolchain@v1
40 | with:
41 | toolchain: nightly
42 | - name: Install cargo audit
43 | run: cargo install cargo-audit
44 | - name: Execute cargo audit
45 | # shlex is currently only being brought by bindgen, which does not use the concerning APIs
46 | # except for testing.
47 | # TODO: remove when shlex gets updated to >=1.3.0 (here and in deny.toml)
48 | run: cargo audit --ignore RUSTSEC-2024-0006
49 |
50 | coverage:
51 | name: Gather coverage data and upload to Codecov
52 | runs-on: ubuntu-latest
53 | steps:
54 | - uses: actions/checkout@v2
55 | with:
56 | ref: "${{ github.event.inputs.rev }}"
57 | - name: Run the container to execute the coverage script
58 | run: docker run -v $(pwd):/tmp/parsec -w /tmp/parsec --security-opt seccomp=unconfined --env RUST_TOOLCHAIN_VERSION=1.67.0 ghcr.io/parallaxsecond/parsec-service-test-all /tmp/parsec/ci.sh coverage
59 | - name: Collect coverage results
60 | run: bash <(curl -s https://codecov.io/bash)
61 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Cargo build directory
2 | /target
3 |
4 | # Mbed Crypto key files
5 | *.psa_its
6 |
7 | # Editor swap files
8 | *.swp
9 |
10 |
11 | tags
12 |
13 | # MacOS folder attributes file
14 | *DS_Store
15 |
16 | # VS Code config folder
17 | *vscode
18 |
19 | # Git patch files
20 | *.patch
21 |
22 | # Parsec key info mappings directories
23 | mappings/
24 | kim-mappings/
25 |
26 | # TPM simulator state file
27 | NVChip
28 | .devcontainer
29 |
30 | # Quickstart tarball
31 | quickstart/*.tar.gz
32 |
33 | # IDE settings files
34 | .idea
35 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "trusted-services-vendor"]
2 | path = trusted-services-vendor
3 | url = https://git.trustedfirmware.org/TS/trusted-services.git
4 | branch = integration
5 |
--------------------------------------------------------------------------------
/.travis.yml.disabled:
--------------------------------------------------------------------------------
1 | # Executing our tests on Arm64 with Travis CI
2 | # The TPM provider Dockerfile does not build on Arm so the all-providers and tpm-provider tests
3 | # are not executed on Aarch64.
4 | if: type = cron
5 | arch: arm64
6 | services:
7 | - docker
8 | jobs:
9 | include:
10 | - name: "Integration tests using Mbed Crypto provider"
11 | env: DOCKER_IMAGE_NAME=mbed-crypto-provider DOCKER_IMAGE_PATH=e2e_tests/provider_cfg/mbed-crypto SCRIPT="ci.sh mbed-crypto"
12 | - name: "Integration tests using PKCS 11 provider"
13 | env: DOCKER_IMAGE_NAME=pkcs11-provider DOCKER_IMAGE_PATH=e2e_tests/provider_cfg/pkcs11 SCRIPT="ci.sh pkcs11"
14 | # Re-enabling these for now, we'll need to fix the issues, otherwise the build is just useless
15 | # PKCS11 tests are failing because of unidentified issues.
16 | # See https://github.com/parallaxsecond/parsec/issues/116
17 | # allow_failures:
18 | # - env: DOCKER_IMAGE_NAME=mbed-crypto-provider DOCKER_IMAGE_PATH=e2e_tests/provider_cfg/mbed-crypto SCRIPT="ci.sh mbed-crypto"
19 | # - env: DOCKER_IMAGE_NAME=pkcs11-provider DOCKER_IMAGE_PATH=e2e_tests/provider_cfg/pkcs11 SCRIPT="ci.sh pkcs11"
20 | script:
21 | - docker build -t $DOCKER_IMAGE_NAME $DOCKER_IMAGE_PATH
22 | - docker run -v $(pwd):/tmp/parsec -w /tmp/parsec $DOCKER_IMAGE_NAME /tmp/parsec/$SCRIPT
23 |
--------------------------------------------------------------------------------
/CODE-OF-CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Parsec Code of Conduct
2 |
3 | Parsec follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
4 |
--------------------------------------------------------------------------------
/CONTRIBUTORS.md:
--------------------------------------------------------------------------------
1 | # Contributors to the Parsec project
2 | This file aims to acknowledge the specific contributors referred to in the "Contributors to the Parsec project" copyright notice.
3 |
4 | ## Organizations
5 | * Arm Ltd.
6 | * Docker Inc.
7 | * Mirantis Inc.
8 |
9 | ## Individuals
10 | * Anton Antonov (@anta5010)
11 | * Paul Howard (@paulhowardarm)
12 | * Ionut Mihalcea (@ionut-arm)
13 | * Hugues de Valon (@hug-dev)
14 | * Jesper Brynolf (@Superhepper)
15 | * Samuel Bailey (@sbailey-arm)
16 | * Patrick Uiterwijk (@puiterwijk)
17 | * Nicolas Stalder (@nickray)
18 | * Edmund Grimley Evans (@egrimley-arm)
19 | * Matt Davis (@MattDavis00)
20 | * Mohamed Omar Asaker (@mohamedasaker-arm)
21 | * Gowtham Suresh Kumar (@gowthamsk-arm)
22 | * William Brown (@firstyear)
23 | * Tomas Agustin Gonzalez Orlando (@tgonzalezorlandoarm)
24 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "parsec-service"
3 | version = "1.4.1"
4 | authors = ["Parsec Project Contributors"]
5 | description = "A language-agnostic API to secure services in a platform-agnostic way"
6 | license = "Apache-2.0"
7 | repository = "https://github.com/parallaxsecond/parsec"
8 | readme = "README.md"
9 | keywords = ["security", "service"]
10 | categories = ["cryptography", "hardware-support"]
11 | edition = "2018"
12 | rust-version = "1.67.0"
13 |
14 | [[bin]]
15 | name = "parsec"
16 | path = "src/bin/main.rs"
17 |
18 | [dependencies]
19 | parsec-interface = "0.29.1"
20 | rand = { version = "0.8.3", features = ["small_rng"], optional = true }
21 | base64 = "0.21.0"
22 | threadpool = "1.8.1"
23 | signal-hook = "0.3.4"
24 | sd-notify = "0.4.1"
25 | toml = "0.8.0"
26 | serde = { version = "1.0.123", features = ["derive"] }
27 | env_logger = "0.10.0"
28 | log = { version = "0.4.14", features = ["serde"] }
29 | cryptoki = { version = "0.6.0", optional = true, default-features = false }
30 | picky-asn1-der = { version = "0.4.0", optional = true }
31 | picky-asn1 = { version = "0.8.0", optional = true }
32 | tss-esapi = { version = "7.5.0", optional = true }
33 | bincode = "1.3.1"
34 | # TODO: Fixed until the MSRV is bumped!
35 | clap = { version = "=4.3.24", features = ["derive", "std"] }
36 | derivative = "2.2.0"
37 | hex = { version = "0.4.2", optional = true }
38 | psa-crypto = { version = "0.12.0", default-features = false, features = ["operations","std"], optional = true }
39 | zeroize = { version = "1.2.0", features = ["zeroize_derive"] }
40 | picky-asn1-x509 = { version = "0.12.0", optional = true }
41 | libc = "0.2.86"
42 | anyhow = "1.0.38"
43 | rust-cryptoauthlib = { version = "0.4.5", optional = true }
44 | spiffe = { version = "0.2.1", optional = true }
45 | prost = { version = "0.9.0", optional = true }
46 | rusqlite = { version = "0.29.0", features = ["bundled"] }
47 | num-traits = "0.2.14"
48 |
49 | [dev-dependencies]
50 | rand = { version = "0.8.3", features = ["small_rng"] }
51 | rust-cryptoauthlib = { version = "0.4.4", features=["software-backend"]}
52 |
53 |
54 | [build-dependencies]
55 | bindgen = { version = "0.66.1", optional = true }
56 | prost-build = { version = "0.9.0", optional = true }
57 |
58 | [package.metadata.docs.rs]
59 | features = ["pkcs11-provider", "tpm-provider", "mbed-crypto-provider", "cryptoauthlib-provider", "direct-authenticator"]
60 |
61 | # The features should not be modified in a breaking way.
62 | # See https://github.com/parallaxsecond/parsec/issues/408 for details.
63 | [features]
64 | default = ["unix-peer-credentials-authenticator"]
65 |
66 | # Providers
67 | mbed-crypto-provider = ["psa-crypto"]
68 | pkcs11-provider = ["cryptoki", "picky-asn1-der", "picky-asn1", "picky-asn1-x509", "psa-crypto", "rand", "hex"]
69 | tpm-provider = ["tss-esapi", "picky-asn1-der", "picky-asn1", "picky-asn1-x509", "hex"]
70 | cryptoauthlib-provider = ["rust-cryptoauthlib"]
71 | trusted-service-provider = ["psa-crypto", "bindgen", "prost-build", "prost"]
72 | all-providers = ["tpm-provider", "pkcs11-provider", "mbed-crypto-provider", "trusted-service-provider"]
73 |
74 | # Authenticators
75 | direct-authenticator = []
76 | unix-peer-credentials-authenticator = []
77 | jwt-svid-authenticator = ["spiffe"]
78 | all-authenticators = ["direct-authenticator", "unix-peer-credentials-authenticator", "jwt-svid-authenticator"]
79 |
--------------------------------------------------------------------------------
/MAINTAINERS.toml:
--------------------------------------------------------------------------------
1 | # Parsec maintainers file
2 | #
3 | # This file lists the maintainers of the parallaxsecond/parsec project.
4 | #
5 | # Its structure is inspired from the maintainers files in the Docker Github
6 | # repositories. Please see the MAINTAINERS file in docker/opensource for more
7 | # information.
8 |
9 | [maintainers]
10 |
11 | # Core maintainers of the project.
12 |
13 | [maintainers.core]
14 | people = [
15 | "adamparco",
16 | "heavypackets",
17 | "hug-dev",
18 | "ionut-arm",
19 | "justincormack",
20 | "paulhowardarm",
21 | "anta5010",
22 | "gowthamsk-arm",
23 | "mohamedasaker-arm",
24 | "tgonzalezorlandoarm",
25 | ]
26 |
27 | [people]
28 |
29 | # A reference list of all people associated with the project.
30 |
31 | [people.adamparco]
32 | Name = "Adam Parco"
33 | Email = "aparco@mirantis.com"
34 | GitHub = "adamparco"
35 |
36 | [people.heavypackets]
37 | Name = "Sabree Blackmon"
38 | Email = "sabree.blackmon@docker.com"
39 | GitHub = "heavypackets"
40 |
41 | [people.hug-dev]
42 | Name = "Hugues de Valon"
43 | Email = "hugues.de-valon@einride.tech"
44 | GitHub = "hug-dev"
45 |
46 | [people.ionut-arm]
47 | Name = "Ionut Mihalcea"
48 | Email = "ionut.mihalcea@arm.com"
49 | GitHub = "ionut-arm"
50 |
51 | [people.justincormack]
52 | Name = "Justin Cormack"
53 | Email = "justin.cormack@docker.com"
54 | GitHub = "justincormack"
55 |
56 | [people.paulhowardarm]
57 | Name = "Paul Howard"
58 | Email = "paul.howard@arm.com"
59 | GitHub = "paulhowardarm"
60 |
61 | [people.anta5010]
62 | Name = "Anton Antonov"
63 | Email = "anton.antonov@arm.com"
64 | GitHub = "anta5010"
65 |
66 | [people.gowthamsk-arm]
67 | Name = "Gowtham Suresh Kumar"
68 | Email = "gowtham.sureshkumar@arm.com"
69 | GitHub = "gowthamsk-arm"
70 |
71 | [people.mohamedasaker-arm]
72 | Name = "Mohamed Omar Asaker"
73 | Email = "mohamed.omarasaker@arm.com"
74 | GitHub = "mohamedasaker-arm"
75 |
76 | [people.tgonzalezorlandoarm]
77 | Name = "Tomás Agustín González Orlando"
78 | Email = "tomasagustin.gonzalezorlando@arm.com"
79 | GitHub = "tgonzalezorlandoarm"
80 |
--------------------------------------------------------------------------------
/PARTNERS.md:
--------------------------------------------------------------------------------
1 |
5 |
6 | # **Contributing Organizations**
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | **Note**: Arm is contributing to Parsec as part of [Project Cassini](https://www.arm.com/-/media/global/solutions/artificial-intelligence/Project_Cassini.pdf).
17 |
18 | # **Adopters and Industry Partners**
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | # Welcome To PARSEC
16 |
17 | **PARSEC** is the **P**latform **A**bst**R**action for **SEC**urity, an open-source initiative
18 | to provide a common API to hardware security and cryptographic services in a platform-agnostic way. This abstraction layer keeps workloads decoupled from physical platform details, enabling cloud-native delivery flows within the data center and at the edge.
19 |
20 |
21 |
22 |
23 |
24 | Read the Parsec documentation [**online**](https://parallaxsecond.github.io/parsec-book/).
25 |
26 | Read the whitepaper [**Security for the Infrastructure Edge**](https://www.arm.com/-/media/global/people/Security-For-The-Infrastructure-Edge-White-paper-NDA).
27 |
28 |
29 | # Why PARSEC?
30 |
31 | Use Parsec when you need:
32 |
33 | - A **portable interface to your platform's Root of Trust** in order to manage keys and perform cryptographic operations without knowledge of the hardware.
34 | - A simple and portable way to access the **best available security** of your platform in your **preferred programming language**.
35 |
36 | # What PARSEC Provides
37 |
38 | The value proposition of Parsec is that it provides the following:
39 |
40 | - **Abstraction** – a common API that is truly agnostic and based on modern cryptographic principles
41 | - **Mediation** – security as a microservice, brokering access to the hardware and providing isolated key stores in a multi-tenant environment
42 | - **Ergonomics** – a client library ecosystem that brings the API to the fingertips of developers in any programming language: “easy to consume, hard to get wrong”
43 | - **Openness** – an open-source project inviting contributions to enhance the ecosystem both within the service and among its client libraries
44 |
45 | # Maintainers
46 |
47 | PARSEC is a collaborative project. The current list of the individuals and organizations who maintain this project can be found [**here**](./MAINTAINERS.toml).
48 |
49 | # Partner Organizations
50 |
51 | See who is [**using and contributing to PARSEC**](./PARTNERS.md).
52 |
53 | # Getting Started
54 |
55 | If you are running on x86 Linux, check out [this guide](https://parallaxsecond.github.io/parsec-book/getting_started/linux_x86.html) to get started with Parsec quickly!
56 |
57 | For examples of how to access PARSEC as a client application, check [this Rust client documentation](https://docs.rs/parsec-client/*/parsec_client/core/basic_client/struct.BasicClient.html).
58 |
59 | Check the [**user**](https://parallaxsecond.github.io/parsec-book/parsec_users.html), [**client developer**](https://parallaxsecond.github.io/parsec-book/parsec_client/index.html) and [**service developer**](https://parallaxsecond.github.io/parsec-book/parsec_service/index.html) guides for more information on building, installing, testing and using Parsec!
60 |
61 | # Community
62 |
63 | Come and ask questions or talk with the Parsec Community in our Slack channel or biweekly meetings.
64 | See the [Community](https://github.com/parallaxsecond/community) repository for more information on how to join.
65 |
66 | # Contributing
67 |
68 | We would be happy for you to contribute to Parsec!
69 | Please check the [**Contribution Guidelines**](https://parallaxsecond.github.io/parsec-book/contributing/index.html)
70 | to know more about the contribution process.
71 | Check the [**open issues**](https://github.com/orgs/parallaxsecond/projects/1) on the board if you
72 | need any ideas 🙂!
73 |
74 | # Security Vulnerability Reporting
75 |
76 | Check [**PARSEC's security policy**](./SECURITY.md).
77 |
78 | # License
79 |
80 | The software is provided under Apache-2.0. Contributions to this project are accepted under the same license.
81 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security policy
2 |
3 | Security is of paramount importance to the Parsec project. We do all we can to identify and fix
4 | issues, however some problems might slip through the cracks. Any efforts towards responsible
5 | disclosure of security problems are greatly appreciated and your contributions will be acknowledged.
6 |
7 | ## Supported versions
8 |
9 | Currently only the most recent version of the Parsec service is eligible for patching. This could
10 | change in the future.
11 |
12 | | Version | Supported |
13 | |------------------|-----------|
14 | | 0.7.0 and higher | ✅ |
15 | | 0.6.0 and lower | ❌ |
16 |
17 | ## Our disclosure policy
18 |
19 | All security vulnerabilities affecting the Parsec service - including those reported using the steps
20 | highlighted below, those discovered during routine testing, and those found in our dependency tree
21 | either through `cargo-audit` or otherwise - will receive [security
22 | advisories](https://github.com/parallaxsecond/parsec/security/advisories) in a timely manner. The
23 | advisories should include sufficient information about the cause, effect, and possible mitigations
24 | for the vulnerability. If any information is missing, or you would like to raise a question about
25 | the advisories, please open an issue in [our repo](https://github.com/parallaxsecond/parsec).
26 |
27 | Efforts to mitigate for the reported vulnerabilities will be tracked using Github issues linked to
28 | the corresponding advisories.
29 |
30 | ## Reporting a vulnerability
31 |
32 | To report a vulnerability, please send an email to
33 | [cncf-parsec-maintainers@lists.cncf.io](mailto:cncf-parsec-maintainers@lists.cncf.io). We will reply
34 | to acknowledge your report and we'll strive to keep you in the loop as we try to reach a resolution.
35 |
--------------------------------------------------------------------------------
/build.rs:
--------------------------------------------------------------------------------
1 | #![allow(clippy::multiple_crate_versions, unused)]
2 | use std::env;
3 | use std::fs::read_dir;
4 | use std::io::{Error, ErrorKind, Result};
5 | use std::path::{Path, PathBuf};
6 |
7 | #[cfg(feature = "trusted-service-provider")]
8 | fn generate_ts_bindings(ts_include_dir: String) -> Result<()> {
9 | let header = ts_include_dir.clone() + "/components/service/locator/interface/service_locator.h";
10 | let encoding_header = ts_include_dir.clone() + "/protocols/rpc/common/packed-c/encoding.h";
11 |
12 | if !Path::new(&header).exists() {
13 | return Err(Error::new(
14 | ErrorKind::Other,
15 | "Trusted Services Locator header is missing. Have you run 'git submodule update --init'?",
16 | ));
17 | }
18 |
19 | println!("cargo:rerun-if-changed={}", header);
20 |
21 | let bindings = bindgen::Builder::default()
22 | .clang_arg(format!("-I{}", ts_include_dir))
23 | .clang_arg(format!(
24 | "-I{}",
25 | ts_include_dir + "/components/rpc/common/interface"
26 | ))
27 | .header(header)
28 | .header(encoding_header)
29 | .generate_comments(false)
30 | .size_t_is_usize(true)
31 | .derive_default(true)
32 | .generate()
33 | .map_err(|_| {
34 | Error::new(
35 | ErrorKind::Other,
36 | "Unable to generate bindings to trusted services locator",
37 | )
38 | })?;
39 | let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
40 | bindings.write_to_file(out_path.join("ts_bindings.rs"))?;
41 |
42 | println!("cargo:rustc-link-lib=dylib=ts");
43 | Ok(())
44 | }
45 |
46 | #[cfg(feature = "trusted-service-provider")]
47 | fn generate_proto_sources(contract_dir: String) -> Result<()> {
48 | let crypto_pb_dir = contract_dir.clone() + "/service/crypto/protobuf";
49 | let dir_entries = read_dir(Path::new(&crypto_pb_dir))?;
50 | let files: Result> = dir_entries
51 | .map(|protos_file| {
52 | protos_file?
53 | .path()
54 | .into_os_string()
55 | .into_string()
56 | .map_err(|_| {
57 | Error::new(
58 | ErrorKind::InvalidData,
59 | "conversion from OsString to String failed",
60 | )
61 | })
62 | })
63 | // Fail the entire operation if there was an error.
64 | .collect();
65 | let proto_files: Vec = files?
66 | .into_iter()
67 | .filter(|string| string.ends_with(".proto"))
68 | .collect();
69 | let files_slices: Vec<&str> = proto_files.iter().map(|file| &file[..]).collect();
70 |
71 | prost_build::compile_protos(&files_slices, &[&contract_dir])
72 | }
73 |
74 | #[cfg(feature = "trusted-service-provider")]
75 | fn main() -> Result<()> {
76 | {
77 | generate_ts_bindings(String::from("trusted-services-vendor"))?;
78 | generate_proto_sources(String::from("trusted-services-vendor/protocols"))?;
79 | }
80 |
81 | Ok(())
82 | }
83 |
84 | #[cfg(not(feature = "trusted-service-provider"))]
85 | fn main() {}
86 |
--------------------------------------------------------------------------------
/doc/images/parsec/ARM1007_PARSEC Logo_ST2_RGB_Stacked_Colour.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/parsec/ARM1007_PARSEC Logo_ST2_RGB_Stacked_Colour.png
--------------------------------------------------------------------------------
/doc/images/parsec/ParsecConceptDiagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/parsec/ParsecConceptDiagram.png
--------------------------------------------------------------------------------
/doc/images/partners/arm/Arm_logo_blue_150LG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/partners/arm/Arm_logo_blue_150LG.png
--------------------------------------------------------------------------------
/doc/images/partners/docker/vertical-logo-monochromatic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/partners/docker/vertical-logo-monochromatic.png
--------------------------------------------------------------------------------
/doc/images/partners/linaro/Logo_linaro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/partners/linaro/Logo_linaro.png
--------------------------------------------------------------------------------
/doc/images/partners/mirantis/mirantis-logo-2color-rgb-transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/partners/mirantis/mirantis-logo-2color-rgb-transparent.png
--------------------------------------------------------------------------------
/doc/images/partners/nxp/NXP_logo_RGB_web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/partners/nxp/NXP_logo_RGB_web.jpg
--------------------------------------------------------------------------------
/doc/images/partners/rancher/rancher-logo-stacked-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/partners/rancher/rancher-logo-stacked-color.png
--------------------------------------------------------------------------------
/doc/images/partners/redhat/Logo-RedHat-D-Color-RGB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/doc/images/partners/redhat/Logo-RedHat-D-Color-RGB.png
--------------------------------------------------------------------------------
/e2e_tests/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | provider_cfg/tmp_config.toml
3 |
--------------------------------------------------------------------------------
/e2e_tests/Cargo.toml:
--------------------------------------------------------------------------------
1 | # This crate should NOT be upstreamed to crates.io; it is only intended for
2 | # PARSEC testing purposes (both locally and on CI)
3 | [package]
4 | name = "e2e_tests"
5 | version = "0.1.0"
6 | authors = ["Parsec Project Contributors"]
7 | description = "End to end testing framework for PARSEC"
8 | license = "Apache-2.0"
9 | edition = "2018"
10 | publish = false
11 |
12 | [dependencies]
13 | serde = { version = "1.0.123", features = ["derive"] }
14 | parsec-client = { version = "0.16.0", features = ["testing", "spiffe-auth"] }
15 | log = "0.4.14"
16 | # Compatible version with crate rsa
17 | rand = "0.7.3"
18 | env_logger = "0.10.0"
19 | stdext = "0.3.1"
20 | tss-esapi = { version = "7.5.0", optional = true }
21 |
22 | [dev-dependencies]
23 | ring = "0.16.20"
24 | rsa = "0.3.0"
25 | picky-asn1-x509 = "0.12.0"
26 | base64 = "0.21.0"
27 | num_cpus = "1.13.0"
28 | picky-asn1-der = "0.4.0"
29 | picky-asn1 = "0.8.0"
30 | sha2 = "0.9.3"
31 | serial_test = "0.5.1"
32 | regex = "1.6.0"
33 | cryptoki = { version = "0.6.0", default-features = false }
34 | snailquote = "0.3.1"
35 |
36 | [features]
37 | mbed-crypto-provider = []
38 | tpm-provider = ["tss-esapi"]
39 | pkcs11-provider = []
40 | cryptoauthlib-provider = []
41 | trusted-service-provider = []
42 | all-providers = ["pkcs11-provider","tpm-provider","mbed-crypto-provider","cryptoauthlib-provider","trusted-service-provider"]
43 |
--------------------------------------------------------------------------------
/e2e_tests/docker_image/_exec_wrapper:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | RUSTUP_HOME=/opt/rust exec /opt/rust/bin/${0##*/} "$@"
--------------------------------------------------------------------------------
/e2e_tests/docker_image/cross-compile-tss.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2021 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | # Cross compile the tpm2-tss library (and its dependencies) for a given target
7 | # In order to cross-compile the TSS library we need to also cross-compile OpenSSL
8 |
9 | set -xeuf -o pipefail
10 |
11 | # Prepare directory for cross-compiled OpenSSL files
12 | mkdir -p /tmp/$1
13 | export INSTALL_DIR=/tmp/$1
14 |
15 | pushd /tmp/openssl
16 | # Compile and copy files over
17 | ./Configure $2 shared --prefix=$INSTALL_DIR --openssldir=$INSTALL_DIR/openssl --cross-compile-prefix=$1-
18 | make clean
19 | make depend
20 | make -j$(nproc)
21 | make install
22 | popd
23 |
24 | unset INSTALL_DIR
25 |
26 | # Prepare directory for cross-compiled TSS lib
27 | # `DESTDIR` is used in `make install` below to set the root of the installation paths.
28 | # The `./configure` script accepts a `--prefix` input variable which sets the same root,
29 | # but also adds it to the paths in `.pc` files used by `pkg-config`. This prevents the
30 | # use of `PKG_CONFIG_SYSROOT_DIR`.
31 | export DESTDIR=/tmp/$1
32 |
33 | pushd /tmp/tpm2-tss
34 | # Compile and copy files over
35 | ./bootstrap
36 | ./configure --build=x86_64-pc-linux-gnu --host=$1 CC=$1-gcc \
37 | LIBCRYPTO_CFLAGS="-I/tmp/$1/include" LIBCRYPTO_LIBS="-L/tmp/$1/lib -lcrypto"
38 | make clean
39 | make -j$(nproc)
40 | make install
41 | popd
42 |
43 | unset DESTDIR
--------------------------------------------------------------------------------
/e2e_tests/docker_image/import-old-e2e-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2021 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | # These commands are made to import the oldest version of the end-to-end tests to check that they
7 | # still work with the current version of the Parsec service.
8 |
9 | set -xeuf -o pipefail
10 |
11 | git clone https://github.com/parallaxsecond/parsec.git
12 | cd parsec
13 | # This commit is the oldest one which still works with current Parsec version.
14 | # It works with the Rust client version 0.6.0
15 | git checkout 2fee72fc64871472edf141906bf7f55bd59a2f8d
16 | mv e2e_tests /tmp/old_e2e_tests
17 | cd ..
18 | rm -rf parsec
19 | # Compiling the tests so that it's faster on the CI
20 | RUST_BACKTRACE=1 cargo test --no-run --manifest-path /tmp/old_e2e_tests/Cargo.toml
21 |
--------------------------------------------------------------------------------
/e2e_tests/docker_image/parsec-service-test-cross-compile.Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Contributors to the Parsec project.
2 | # SPDX-License-Identifier: Apache-2.0
3 | FROM ghcr.io/parallaxsecond/parsec-service-test-all
4 |
5 | # Install aarch64-none-linux-gnu cross compilation toolchain
6 | RUN wget https://developer.arm.com/-/media/Files/downloads/gnu-a/9.2-2019.12/binrel/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz?revision=61c3be5d-5175-4db6-9030-b565aae9f766 -O aarch64-gcc.tar.xz
7 | RUN tar --strip-components=1 -C /usr/ -xvf aarch64-gcc.tar.xz
8 | RUN rm aarch64-gcc.tar.xz
9 |
10 | # Install Trusted Services lib compiled for aarch64
11 | # Setup git config for patching dependencies
12 | RUN git config --global user.email "some@email.com"
13 | RUN git config --global user.name "Parsec Team"
14 | RUN git clone https://git.trustedfirmware.org/TS/trusted-services.git --branch main \
15 | && cd trusted-services \
16 | && git reset --hard b27d4163e01065d1203bd71ffa6562a651f77a13
17 | # Install correct python dependencies
18 | RUN pip3 install -r trusted-services/requirements.txt
19 | RUN cd trusted-services/deployments/libts/arm-linux/ \
20 | && cmake . \
21 | && make \
22 | && cp libts.so* /usr/local/lib/
23 | RUN rm -rf trusted-services
24 |
25 | # Install cross-compilers
26 | RUN apt install -y gcc-multilib
27 | RUN apt install -y gcc-arm-linux-gnueabihf
28 | RUN apt install -y gcc-aarch64-linux-gnu
29 | RUN apt install -y gcc-i686-linux-gnu libc6-dev-i386
30 |
31 | WORKDIR /tmp
32 |
33 | # Get OpenSSL source code
34 | ENV OPENSSL_VERSION="OpenSSL_1_1_1j"
35 | RUN git clone https://github.com/openssl/openssl.git --branch $OPENSSL_VERSION
36 |
37 | # Get TPM2 TSS source code
38 | ENV TPM2_TSS_VERSION="2.3.3"
39 | RUN git clone https://github.com/tpm2-software/tpm2-tss --branch $TPM2_TSS_VERSION
40 |
41 | # Copy TSS cross-compilation script
42 | COPY cross-compile-tss.sh /tmp/
43 | # Cross-compile TPM2 TSS and OpenSSL for Linux on aarch64
44 | RUN ./cross-compile-tss.sh aarch64-linux-gnu linux-generic64
45 | # Cross-compile TPM2 TSS and OpenSSL for Linux on armv7
46 | RUN ./cross-compile-tss.sh arm-linux-gnueabihf linux-generic32
47 | # Cross-compile TPM2 TSS and OpenSSL for Linux on i686
48 | RUN ./cross-compile-tss.sh i686-linux-gnu linux-generic32
49 |
50 | RUN rustup target add armv7-unknown-linux-gnueabihf
51 | RUN rustup target add aarch64-unknown-linux-gnu
52 | RUN rustup target add i686-unknown-linux-gnu
53 |
--------------------------------------------------------------------------------
/e2e_tests/fake_mappings/cGFyc2VjLXRvb2w=/1/dG90bw==:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/e2e_tests/fake_mappings/cGFyc2VjLXRvb2w=/2/dG90bw==:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parallaxsecond/parsec/5b2c4904d96808a5fb98a599f5304acef8b26dda/e2e_tests/fake_mappings/cGFyc2VjLXRvb2w=/2/dG90bw==
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/all/config.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | timeout = 200 # in milliseconds
13 | socket_path = "/tmp/parsec.sock"
14 |
15 | [authenticator]
16 | auth_type = "Direct"
17 | admins = [ { name = "list_clients test" }, { name = "1000" }, { name = "client1" }, { name = "spiffe://example.org/parsec-client-1" } ]
18 | #workload_endpoint="unix:///tmp/agent.sock"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "MbedCrypto"
27 | key_info_manager = "sqlite-manager"
28 |
29 | [[provider]]
30 | provider_type = "Tpm"
31 | key_info_manager = "sqlite-manager"
32 | tcti = "mssim"
33 | owner_hierarchy_auth = "tpm_pass"
34 |
35 | [[provider]]
36 | provider_type = "Pkcs11"
37 | key_info_manager = "sqlite-manager"
38 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
39 | user_pin = "123456"
40 | # The slot_number mandatory field is going to replace the following line with a valid number
41 | # slot_number
42 |
43 |
44 | # CAL provider and hardware abstraction crate are unmaintained; See #585
45 | # [[provider]]
46 | # provider_type = "CryptoAuthLib"
47 | # key_info_manager = "sqlite-manager"
48 | # device_type = "always-success"
49 | # iface_type = "test-interface"
50 | # wake_delay = 1500
51 | # rx_retries = 20
52 | # # i2c parameters for i2c-pseudo proxy
53 | # slave_address = 0xc0
54 | # bus = 1
55 | # baud = 400000
56 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/all/on-disk-kim-all-providers.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | timeout = 200 # in milliseconds
13 | socket_path = "/tmp/parsec.sock"
14 |
15 | [authenticator]
16 | auth_type = "Direct"
17 | admins = [ { name = "list_clients test" }, { name = "1000" }, { name = "client1" }, { name = "spiffe://example.org/parsec-client-1" } ]
18 | #workload_endpoint="unix:///tmp/agent.sock"
19 |
20 | [[key_manager]]
21 | name = "on-disk-manager"
22 | manager_type = "OnDisk"
23 | store_path = "./mappings"
24 |
25 | [[provider]]
26 | provider_type = "MbedCrypto"
27 | key_info_manager = "on-disk-manager"
28 |
29 | [[provider]]
30 | provider_type = "Tpm"
31 | key_info_manager = "on-disk-manager"
32 | tcti = "mssim"
33 | owner_hierarchy_auth = "tpm_pass"
34 |
35 | [[provider]]
36 | provider_type = "Pkcs11"
37 | key_info_manager = "on-disk-manager"
38 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
39 | user_pin = "123456"
40 | # The slot_number mandatory field is going to replace the following line with a valid number
41 | # slot_number
42 |
43 | # CAL provider and hardware abstraction crate are unmaintained; See #585
44 | # [[provider]]
45 | # provider_type = "CryptoAuthLib"
46 | # key_info_manager = "on-disk-manager"
47 | # device_type = "always-success"
48 | # iface_type = "test-interface"
49 | # wake_delay = 1500
50 | # rx_retries = 20
51 | # # i2c parameters for i2c-pseudo proxy
52 | # slave_address = 0xc0
53 | # bus = 1
54 | # baud = 400000
55 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/cryptoauthlib/cal_access_keys.toml:
--------------------------------------------------------------------------------
1 | #########################################################################
2 | # The example configuration file with access keys.
3 | #
4 | # Note! The contents of this file may be considered sensitive from
5 | # a security point of view. Therefore this file should be stored in
6 | # a secure folder, where only 'parsec' user may read its contents.
7 | # The keys MUST be exactly the same as the ones stored in given slots.
8 | # This means there may be a need to generate file per cryptochip.
9 | #
10 | # Safe to be used in github CI.
11 | #########################################################################
12 | [[access_keys]]
13 | # Cryptochip slot index, 0..15
14 | slot = 6
15 | # Access key - 32 bytes long octet string
16 | key = [ 0x4D, 0x50, 0x72, 0x6F, 0x20, 0x49, 0x4F, 0x20, 0x4B, 0x65, 0x79, 0x20, 0x9E, 0x31,
17 | 0xBD, 0x05, 0x82, 0x58, 0x76, 0xCE, 0x37, 0x90, 0xEA, 0x77, 0x42, 0x32, 0xBB, 0x51,
18 | 0x81, 0x49, 0x66, 0x45]
19 |
20 | [[access_keys]]
21 | # Yes, slot number below does not make much sense. But it is not a big issue.
22 | slot = 22
23 | key = [ 0x4E, 0x51, 0x73, 0x70, 0x21, 0x4A, 0x50, 0x21, 0x4C, 0x66, 0x7A, 0x21, 0x9F, 0x32,
24 | 0xBE, 0x06, 0x83, 0x59, 0x77, 0xCF, 0x38, 0x91, 0xEB, 0x78, 0x43, 0x33, 0xBC, 0x52,
25 | 0x82, 0x50, 0x67, 0x46]
26 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/cryptoauthlib/config-sqlite.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | timeout = 200 # in milliseconds
13 | socket_path = "/tmp/parsec.sock"
14 |
15 | [authenticator]
16 | auth_type = "Direct"
17 |
18 | [[key_manager]]
19 | name = "sqlite-manager"
20 | manager_type = "SQLite"
21 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
22 |
23 | [[provider]]
24 | provider_type = "CryptoAuthLib"
25 | key_info_manager = "sqlite-manager"
26 | device_type = "unimplemented-fail"
27 | iface_type = "test-interface"
28 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/cryptoauthlib/config.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 | # Allow deprecated for testing
10 | allow_deprecated = true
11 |
12 | [listener]
13 | listener_type = "DomainSocket"
14 | timeout = 200 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "on-disk-manager"
22 | manager_type = "OnDisk"
23 | store_path = "./mappings"
24 |
25 | [[provider]]
26 | provider_type = "CryptoAuthLib"
27 | key_info_manager = "on-disk-manager"
28 | device_type = "unimplemented-fail"
29 | iface_type = "test-interface"
30 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/cryptoauthlib/config_508a.toml:
--------------------------------------------------------------------------------
1 | #########################################################################
2 | # The example config file for atecc508a cryptochip.
3 | # There must be an I2C bus with a cryptochip soldered, otherwise provider
4 | # instantiation fails.
5 | # Not to be used by github CI.
6 | #########################################################################
7 | [core_settings]
8 | # The CI already timestamps the logs
9 | log_timestamp = false
10 | log_error_details = true
11 |
12 | # The container runs the Parsec service as root, so make sure we disable root
13 | # checks.
14 | allow_root = true
15 |
16 | [listener]
17 | listener_type = "DomainSocket"
18 | timeout = 200 # in milliseconds
19 | socket_path = "/tmp/parsec.sock"
20 |
21 | [authenticator]
22 | auth_type = "Direct"
23 |
24 | [[key_manager]]
25 | name = "on-disk-manager"
26 | manager_type = "OnDisk"
27 | store_path = "./mappings"
28 |
29 | [[provider]]
30 | provider_type = "CryptoAuthLib"
31 | key_info_manager = "on-disk-manager"
32 | device_type = "atecc508a"
33 | iface_type = "i2c"
34 | wake_delay = 1500
35 | rx_retries = 20
36 | # i2c parameters for i2c-pseudo proxy
37 | slave_address = 0xc0
38 | bus = 1
39 | baud = 400000
40 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/cryptoauthlib/config_608a.toml:
--------------------------------------------------------------------------------
1 | #########################################################################
2 | # The example config file for atecc608a cryptochip.
3 | # There must be an I2C bus with a cryptochip soldered, otherwise provider
4 | # instantiation fails.
5 | # Not to be used by github CI.
6 | #########################################################################
7 | [core_settings]
8 | # The CI already timestamps the logs
9 | log_timestamp = false
10 | log_error_details = true
11 |
12 | # The container runs the Parsec service as root, so make sure we disable root
13 | # checks.
14 | allow_root = true
15 |
16 | [listener]
17 | listener_type = "DomainSocket"
18 | timeout = 200 # in milliseconds
19 | socket_path = "/tmp/parsec.sock"
20 |
21 | [authenticator]
22 | auth_type = "Direct"
23 |
24 | [[key_manager]]
25 | name = "on-disk-manager"
26 | manager_type = "OnDisk"
27 | store_path = "./mappings"
28 |
29 | [[provider]]
30 | provider_type = "CryptoAuthLib"
31 | key_info_manager = "on-disk-manager"
32 | device_type = "atecc608a"
33 | iface_type = "i2c"
34 | wake_delay = 1600
35 | rx_retries = 20
36 | # i2c parameters for i2c-pseudo proxy
37 | slave_address = 0xc0
38 | bus = 1
39 | baud = 400000
40 | access_key_file_name = "e2e_tests/provider_cfg/cryptoauthlib/cal_access_keys.toml"
41 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/mbed-crypto/config-sqlite.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "MbedCrypto"
27 | key_info_manager = "sqlite-manager"
28 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/mbed-crypto/config.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 | # Allow deprecated for testing
10 | allow_deprecated = true
11 |
12 | [listener]
13 | listener_type = "DomainSocket"
14 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
15 | # that the service does not hang for very big values of body or authentication length.
16 | timeout = 3000 # in milliseconds
17 | socket_path = "/tmp/parsec.sock"
18 |
19 | [authenticator]
20 | auth_type = "Direct"
21 |
22 | [[key_manager]]
23 | name = "on-disk-manager"
24 | manager_type = "OnDisk"
25 | store_path = "./mappings"
26 |
27 | [[provider]]
28 | provider_type = "MbedCrypto"
29 | key_info_manager = "on-disk-manager"
30 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/pkcs11/config-sqlite.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "123456"
30 | software_public_operations = false
31 | # The slot_number optional field is going to replace the following line with a valid number
32 | # slot_number
33 | # The token serial_number optional field is going to replace the following line with a valid number
34 | # serial_number
35 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/pkcs11/config.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 | # Allow deprecated for testing
10 | allow_deprecated = true
11 |
12 | [listener]
13 | listener_type = "DomainSocket"
14 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
15 | # that the service does not hang for very big values of body or authentication length.
16 | timeout = 3000 # in milliseconds
17 | socket_path = "/tmp/parsec.sock"
18 |
19 | [authenticator]
20 | auth_type = "Direct"
21 |
22 | [[key_manager]]
23 | name = "on-disk-manager"
24 | manager_type = "OnDisk"
25 | store_path = "./mappings"
26 |
27 | [[provider]]
28 | provider_type = "Pkcs11"
29 | key_info_manager = "on-disk-manager"
30 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
31 | user_pin = "123456"
32 | software_public_operations = false
33 | # The slot_number optional field is going to replace the following line with a valid number
34 | # slot_number
35 | # The token serial_number optional field is going to replace the following line with a valid number
36 | # serial_number
37 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/tpm/config-sqlite.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Tpm"
27 | key_info_manager = "sqlite-manager"
28 | tcti = "mssim:host=127.0.0.1,port=2321"
29 | owner_hierarchy_auth = "hex:74706d5f70617373" # "tpm_pass" in hex
30 | endorsement_hierarchy_auth = "str:endorsement_pass"
31 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/tpm/config.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 | # Allow deprecated for testing
10 | allow_deprecated = true
11 |
12 | [listener]
13 | listener_type = "DomainSocket"
14 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
15 | # that the service does not hang for very big values of body or authentication length.
16 | timeout = 3000 # in milliseconds
17 | socket_path = "/tmp/parsec.sock"
18 |
19 | [authenticator]
20 | auth_type = "Direct"
21 |
22 | [[key_manager]]
23 | name = "on-disk-manager"
24 | manager_type = "OnDisk"
25 | store_path = "./mappings"
26 |
27 | [[provider]]
28 | provider_type = "Tpm"
29 | key_info_manager = "on-disk-manager"
30 | tcti = "mssim:host=127.0.0.1,port=2321"
31 | owner_hierarchy_auth = "hex:74706d5f70617373" # "tpm_pass" in hex
32 | endorsement_hierarchy_auth = "str:endorsement_pass"
33 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/trusted-service/config-sqlite.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "TrustedService"
27 | key_info_manager = "sqlite-manager"
28 |
--------------------------------------------------------------------------------
/e2e_tests/provider_cfg/trusted-service/config.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 | # Allow deprecated for testing
10 | allow_deprecated = true
11 |
12 | [listener]
13 | listener_type = "DomainSocket"
14 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
15 | # that the service does not hang for very big values of body or authentication length.
16 | timeout = 3000 # in milliseconds
17 | socket_path = "/tmp/parsec.sock"
18 |
19 | [authenticator]
20 | auth_type = "Direct"
21 |
22 | [[key_manager]]
23 | name = "on-disk-manager"
24 | manager_type = "OnDisk"
25 | store_path = "./mappings"
26 |
27 | [[provider]]
28 | provider_type = "TrustedService"
29 | key_info_manager = "on-disk-manager"
30 |
--------------------------------------------------------------------------------
/e2e_tests/src/raw_request.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use parsec_client::core::interface::requests::request::RawHeader;
4 | use parsec_client::core::interface::requests::{Response, Result};
5 | use std::env;
6 | use std::io::Write;
7 | use std::os::unix::net::UnixStream;
8 | use std::thread;
9 | use std::time::Duration;
10 |
11 | const MAX_BODY_SIZE: usize = 1 << 31;
12 |
13 | /// Low level client structure to send a `Request` and get a `Response`.
14 | #[derive(Copy, Clone, Debug)]
15 | pub struct RawRequestClient;
16 |
17 | const TIMEOUT: Duration = Duration::from_secs(60);
18 |
19 | #[allow(clippy::new_without_default)]
20 | impl RawRequestClient {
21 | /// Send a raw request.
22 | ///
23 | /// Send a raw request header and a collection of bytes.
24 | pub fn send_raw_request(&mut self, request_hdr: RawHeader, bytes: Vec) -> Result {
25 | //Check the envrionment variable before using the default test path
26 | let socket_path = env::var("PARSEC_SERVICE_ENDPOINT")
27 | .unwrap_or_else(|_| "/tmp/parsec.sock".into())
28 | .replace("unix:", "");
29 |
30 | // Try to connect once, wait for a timeout until trying again.
31 | let mut stream = UnixStream::connect(&socket_path);
32 | if stream.is_err() {
33 | thread::sleep(TIMEOUT);
34 | stream = UnixStream::connect(&socket_path);
35 | }
36 | let mut stream = stream.expect("Failed to connect to Unix socket");
37 |
38 | stream
39 | .set_read_timeout(Some(TIMEOUT))
40 | .expect("Failed to set read timeout for stream");
41 | stream
42 | .set_write_timeout(Some(TIMEOUT))
43 | .expect("Failed to set write timeout for stream");
44 |
45 | request_hdr
46 | .write_to_stream(&mut stream)
47 | .expect("Failed to write raw header to socket");
48 | stream
49 | .write_all(&bytes)
50 | .expect("Failed to write bytes to stream");
51 |
52 | Response::read_from_stream(&mut stream, MAX_BODY_SIZE)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/allow_deprecated.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 | allow_deprecated = true
6 |
7 | [listener]
8 | listener_type = "DomainSocket"
9 | timeout = 200 # in milliseconds
10 | socket_path = "/tmp/parsec.sock"
11 |
12 | [authenticator]
13 | auth_type = "Direct"
14 |
15 | [[key_manager]]
16 | name = "sqlite-manager"
17 | manager_type = "SQLite"
18 | database_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
19 |
20 | [[provider]]
21 | provider_type = "MbedCrypto"
22 | key_info_manager = "sqlite-manager"
23 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/allow_export.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "sqlite-manager"
16 | manager_type = "SQLite"
17 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
18 |
19 | [[provider]]
20 | provider_type = "Pkcs11"
21 | key_info_manager = "sqlite-manager"
22 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
23 | user_pin = "123456"
24 | # The slot_number mandatory field is going to replace the following line with a valid number
25 | # slot_number
26 | allow_export = false
27 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/list_providers_1.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "sqlite-manager"
16 | manager_type = "SQLite"
17 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
18 |
19 | [[provider]]
20 | provider_type = "MbedCrypto"
21 | key_info_manager = "sqlite-manager"
22 |
23 | [[provider]]
24 | provider_type = "Tpm"
25 | key_info_manager = "sqlite-manager"
26 | tcti = "mssim"
27 | owner_hierarchy_auth = "tpm_pass"
28 |
29 | [[provider]]
30 | provider_type = "Pkcs11"
31 | key_info_manager = "sqlite-manager"
32 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
33 | user_pin = "123456"
34 | # The slot_number mandatory field is going to replace the following line with a valid number
35 | # slot_number
36 |
37 | # CAL provider and hardware abstraction crate are unmaintained; See #585
38 | # [[provider]]
39 | # provider_type = "CryptoAuthLib"
40 | # key_info_manager = "sqlite-manager"
41 | # device_type = "always-success"
42 | # iface_type = "test-interface"
43 | # wake_delay = 1500
44 | # rx_retries = 20
45 | # # i2c parameters for i2c-pseudo proxy
46 | # slave_address = 0xc0
47 | # bus = 1
48 | # baud = 400000
49 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/list_providers_2.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "sqlite-manager"
16 | manager_type = "SQLite"
17 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
18 |
19 | [[provider]]
20 | provider_type = "Pkcs11"
21 | key_info_manager = "sqlite-manager"
22 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
23 | user_pin = "123456"
24 | # The slot_number mandatory field is going to replace the following line with a valid number
25 | # slot_number
26 |
27 | [[provider]]
28 | provider_type = "MbedCrypto"
29 | key_info_manager = "sqlite-manager"
30 |
31 | [[provider]]
32 | provider_type = "Tpm"
33 | key_info_manager = "sqlite-manager"
34 | tcti = "mssim"
35 | owner_hierarchy_auth = "tpm_pass"
36 |
37 | # CAL provider and hardware abstraction crate are unmaintained; See #585
38 | # [[provider]]
39 | # provider_type = "CryptoAuthLib"
40 | # key_info_manager = "sqlite-manager"
41 | # device_type = "always-success"
42 | # iface_type = "test-interface"
43 | # wake_delay = 1500
44 | # rx_retries = 20
45 | # # i2c parameters for i2c-pseudo proxy
46 | # slave_address = 0xc0
47 | # bus = 1
48 | # baud = 400000
49 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/no_endorsement_auth.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Tpm"
27 | key_info_manager = "sqlite-manager"
28 | tcti = "mssim:host=127.0.0.1,port=2321"
29 | owner_hierarchy_auth = "hex:74706d5f70617373" # "tpm_pass" in hex
30 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/no_serial_or_slot_number.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "123456"
30 | # Slot number not entered, it should be automatically chosen by the service.
31 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/no_tpm_support.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "sqlite-manager"
16 | manager_type = "SQLite"
17 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
18 |
19 | [[provider]]
20 | provider_type = "MbedCrypto"
21 | key_info_manager = "sqlite-manager"
22 |
23 | [[provider]]
24 | provider_type = "Tpm"
25 | key_info_manager = "sqlite-manager"
26 | # There shoudn't be a real TPM available on the CI
27 | tcti = "device"
28 | owner_hierarchy_auth = ""
29 | skip_if_no_tpm = true
30 |
31 | [[provider]]
32 | provider_type = "Pkcs11"
33 | key_info_manager = "sqlite-manager"
34 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
35 | user_pin = "123456"
36 | # The slot_number mandatory field is going to replace the following line with a valid number
37 | # slot_number
38 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/no_user_pin.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | # The service should start without the user pin
30 | #user_pin = "123456"
31 | # The slot_number mandatory field is going to replace the following line with a valid number
32 | # slot_number
33 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/pkcs11_pin_hex_fmt.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | database_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "hex:1100220033"
30 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/pkcs11_pin_str_fmt_with_hex_word.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | database_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "str:hex:1100220033"
30 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/pkcs11_software.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 | allow_deprecated = true
10 |
11 | [listener]
12 | listener_type = "DomainSocket"
13 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
14 | # that the service does not hang for very big values of body or authentication length.
15 | timeout = 3000 # in milliseconds
16 | socket_path = "/tmp/parsec.sock"
17 |
18 | [authenticator]
19 | auth_type = "Direct"
20 |
21 | [[key_manager]]
22 | name = "sqlite-manager"
23 | manager_type = "SQLite"
24 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
25 |
26 | [[provider]]
27 | provider_type = "Pkcs11"
28 | key_info_manager = "sqlite-manager"
29 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
30 | user_pin = "123456"
31 | software_public_operations = true
32 | # The slot_number mandatory field is going to replace the following line with a valid number
33 | # slot_number
34 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/reject_deprecated.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 | allow_deprecated = false
6 |
7 | [listener]
8 | listener_type = "DomainSocket"
9 | timeout = 200 # in milliseconds
10 | socket_path = "/tmp/parsec.sock"
11 |
12 | [authenticator]
13 | auth_type = "Direct"
14 |
15 | [[key_manager]]
16 | name = "sqlite-manager"
17 | manager_type = "SQLite"
18 | database_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
19 |
20 | [[provider]]
21 | provider_type = "MbedCrypto"
22 | key_info_manager = "sqlite-manager"
23 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/serial_number_only.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "123456"
30 | # The serial number optional field is going to replace the following line with a valid number
31 | # serial_number
32 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/serial_number_padding.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "123456"
30 | # The serial number optional field is going to replace the following line with a valid number
31 | # serial_number
32 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/slot_number_only.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "123456"
30 | # The slot_number optional field is going to replace the following line with a valid number
31 | # slot_number
32 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/slot_numbers_mismatch.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "Pkcs11"
27 | key_info_manager = "sqlite-manager"
28 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
29 | user_pin = "123456"
30 | # A dummy slot_number
31 | slot_number=12345678
32 | # The serial number optional field is going to replace the following line with a valid number
33 | # serial_number
34 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/ts_pkcs11_cross.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | # The container runs the Parsec service as root, so make sure we disable root
7 | # checks.
8 | allow_root = true
9 |
10 | [listener]
11 | listener_type = "DomainSocket"
12 | # The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
13 | # that the service does not hang for very big values of body or authentication length.
14 | timeout = 3000 # in milliseconds
15 | socket_path = "/tmp/parsec.sock"
16 |
17 | [authenticator]
18 | auth_type = "Direct"
19 |
20 | [[key_manager]]
21 | name = "sqlite-manager"
22 | manager_type = "SQLite"
23 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
24 |
25 | [[provider]]
26 | provider_type = "TrustedService"
27 | key_info_manager = "sqlite-manager"
28 |
29 | [[provider]]
30 | provider_type = "Pkcs11"
31 | key_info_manager = "sqlite-manager"
32 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
33 | user_pin = "123456"
34 | software_public_operations = true
35 | # The slot_number mandatory field is going to replace the following line with a valid number
36 | # slot_number
37 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/config/tomls/various_field_check.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | allow_root = true
3 | thread_pool_size = 2
4 | idle_listener_sleep_duration = 12
5 | log_level = "trace"
6 | log_timestamp = true
7 | # 1 KiB max for requests
8 | body_len_limit = 1024
9 | log_error_details = true
10 | # 1 KiB max for responses
11 | buffer_size_limit = 1024
12 |
13 | [listener]
14 | listener_type = "DomainSocket"
15 | timeout = 202
16 | socket_path = "/tmp/toto.sock"
17 |
18 | [authenticator]
19 | auth_type = "Direct"
20 |
21 | [[key_manager]]
22 | name = "I-want-to-speak-to-the-manager"
23 | manager_type = "SQLite"
24 | sqlite_db_path = "./kim-mappings/sqlite/sqlite-key-info-manager.sqlite3"
25 |
26 | [[provider]]
27 | provider_type = "MbedCrypto"
28 | key_info_manager = "I-want-to-speak-to-the-manager"
29 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/logging.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | use e2e_tests::TestClient;
5 | use parsec_client::core::interface::requests::ProviderId;
6 | use std::fs;
7 |
8 | // Ignore this test case for manual test runs. This is executed on the CI after the parsec service logs are
9 | // redirected to a log file (parsec_logging.txt) for testing purpose.
10 | #[ignore]
11 | #[test]
12 | fn check_log_source() {
13 | let mut client = TestClient::new();
14 |
15 | // Perform key generation and encryption to generate expected logs
16 | client.set_provider(ProviderId::MbedCrypto);
17 | client.set_default_auth(Some("logging".to_string()));
18 | client
19 | .generate_rsa_sign_key(String::from("test_key"))
20 | .unwrap();
21 | let _ = client
22 | .asymmetric_encrypt_message_with_rsapkcs1v15(String::from("test_key"), vec![0xa5; 16])
23 | .unwrap_err();
24 |
25 | // Read parsec log file contents
26 | let logs: String =
27 | fs::read_to_string("/tmp/parsec/parsec_logging.txt").expect("Failure in reading the file");
28 |
29 | // Ensure logs contains INFO, WARN and ERROR message arising from different modules and crates
30 | assert!(logs.contains(
31 | "[INFO parsec_service::front::front_end] New request received without authentication"
32 | ));
33 | assert!(logs
34 | .contains("[WARN parsec_service::key_info_managers::on_disk_manager] Saving Key Triple"));
35 | assert!(logs.contains(
36 | "[ERROR psa_crypto::types::key] Key attributes do not permit encrypting messages."
37 | ));
38 | }
39 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | mod config;
5 | mod cross;
6 | mod logging;
7 | mod multitenancy;
8 | mod normal;
9 |
--------------------------------------------------------------------------------
/e2e_tests/tests/all_providers/multitenancy.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use e2e_tests::TestClient;
4 | use parsec_client::core::interface::requests::{ProviderId, ResponseStatus};
5 |
6 | // These tests are executed by different users in the following order:
7 | // 1. client1_before is executed as parsec-client-1
8 | // 2. client2 is executed as parsec-client-2
9 | // 3. client1_after is executed as parsec-client-1
10 | //
11 | // They are executed against all possible authenticators in Parsec.
12 | //
13 | // client1 will be configured as an admin.
14 |
15 | fn get_key_name(provider: &ProviderId) -> String {
16 | format!("{}-multitenant", provider)
17 | }
18 |
19 | #[test]
20 | fn client1_before() {
21 | // Create one key on each provider
22 | let mut client = TestClient::new();
23 | client.do_not_destroy_keys();
24 | client.set_default_auth(Some("client1".to_string()));
25 |
26 | for provider in [ProviderId::MbedCrypto, ProviderId::Pkcs11, ProviderId::Tpm].iter() {
27 | client.set_provider(*provider);
28 | client
29 | .generate_rsa_sign_key(get_key_name(provider))
30 | .unwrap();
31 | }
32 |
33 | let clients = client.list_clients().unwrap();
34 | assert_eq!(clients.len(), 1);
35 | }
36 |
37 | #[test]
38 | fn client2() {
39 | let mut client = TestClient::new();
40 | client.do_not_destroy_keys();
41 | client.set_default_auth(Some("client2".to_string()));
42 |
43 | // Try to list those keys
44 | let keys = client.list_keys().unwrap();
45 | assert!(keys.is_empty());
46 |
47 | for provider in [ProviderId::MbedCrypto, ProviderId::Pkcs11, ProviderId::Tpm].iter() {
48 | client.set_provider(*provider);
49 | assert_eq!(
50 | client
51 | .export_public_key(get_key_name(provider))
52 | .unwrap_err(),
53 | ResponseStatus::PsaErrorDoesNotExist
54 | );
55 | assert_eq!(
56 | client.destroy_key(get_key_name(provider)).unwrap_err(),
57 | ResponseStatus::PsaErrorDoesNotExist
58 | );
59 | client
60 | .generate_rsa_sign_key(get_key_name(provider))
61 | .unwrap();
62 | client.destroy_key(get_key_name(provider)).unwrap();
63 | }
64 |
65 | assert_eq!(
66 | client.list_clients().unwrap_err(),
67 | ResponseStatus::AdminOperation
68 | );
69 | assert_eq!(
70 | client.delete_client("toto".to_string()).unwrap_err(),
71 | ResponseStatus::AdminOperation
72 | );
73 | client
74 | .generate_rsa_sign_key("client2-key".to_string())
75 | .unwrap();
76 | }
77 |
78 | #[test]
79 | fn client1_after() {
80 | let mut client = TestClient::new();
81 | client.do_not_destroy_keys();
82 | client.set_default_auth(Some("client1".to_string()));
83 |
84 | // Verify all keys are still there and can be used
85 | let keys = client.list_keys().unwrap();
86 | assert_eq!(keys.len(), 3);
87 |
88 | // Destroy the keys
89 | for provider in [ProviderId::MbedCrypto, ProviderId::Pkcs11, ProviderId::Tpm].iter() {
90 | client.set_provider(*provider);
91 | client.destroy_key(get_key_name(provider)).unwrap();
92 | }
93 |
94 | client
95 | .generate_rsa_sign_key("client1-key".to_string())
96 | .unwrap();
97 | let mut clients = client.list_clients().unwrap();
98 | assert_eq!(clients.len(), 2);
99 | client.delete_client(clients.remove(0)).unwrap();
100 | let keys = client.list_keys().unwrap();
101 | assert_eq!(keys.len(), 0);
102 |
103 | let mut clients = client.list_clients().unwrap();
104 | assert_eq!(clients.len(), 1);
105 | client.delete_client(clients.remove(0)).unwrap();
106 | let keys = client.list_keys().unwrap();
107 | assert_eq!(keys.len(), 0);
108 | }
109 |
--------------------------------------------------------------------------------
/e2e_tests/tests/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | #![deny(
5 | nonstandard_style,
6 | dead_code,
7 | improper_ctypes,
8 | non_shorthand_field_patterns,
9 | no_mangle_generic_items,
10 | overflowing_literals,
11 | path_statements,
12 | patterns_in_fns_without_body,
13 | unconditional_recursion,
14 | unused,
15 | unused_allocation,
16 | unused_comparisons,
17 | unused_parens,
18 | while_true,
19 | missing_debug_implementations,
20 | trivial_casts,
21 | trivial_numeric_casts,
22 | unused_extern_crates,
23 | unused_import_braces,
24 | unused_qualifications,
25 | unused_results,
26 | missing_copy_implementations
27 | )]
28 | // This one is hard to avoid.
29 | #![allow(clippy::multiple_crate_versions)]
30 |
31 | #[cfg(feature = "all-providers")]
32 | mod all_providers;
33 | #[cfg(not(feature = "all-providers"))]
34 | mod per_provider;
35 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/key_mappings.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | use e2e_tests::TestClient;
5 | use parsec_client::core::interface::requests::Result;
6 | use parsec_client::core::interface::requests::{Opcode, ResponseStatus};
7 |
8 | const HASH: [u8; 32] = [
9 | 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
10 | 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
11 | ];
12 |
13 | const PLAINTEXT_MESSAGE: [u8; 32] = [
14 | 0x69, 0x3E, 0xDB, 0x1B, 0x22, 0x79, 0x03, 0xF4, 0xC0, 0xBF, 0xD6, 0x91, 0x76, 0x37, 0x84, 0xA2,
15 | 0x94, 0x8E, 0x92, 0x50, 0x35, 0xC2, 0x8C, 0x5C, 0x3C, 0xCA, 0xFE, 0x18, 0xE8, 0x81, 0x37, 0x78,
16 | ];
17 |
18 | // This test tries to use the keys created in the Docker image via the generate-keys.sh script.
19 | // Each provider has a "ecc" and "rsa" key created by the Parsec Tool.
20 | // The ci.sh script also adds fake mappings (mappings which do not link to an existing key) in all
21 | // providers except the TPM one (as for this provider the mapping IS the key).
22 |
23 | #[test]
24 | fn use_and_check() -> Result<()> {
25 | let mut client = TestClient::new();
26 |
27 | client.set_default_auth(Some(String::from("parsec-tool")));
28 |
29 | let keys = client.list_keys()?;
30 | assert!(!keys.is_empty());
31 |
32 | for key in keys {
33 | if key.name.contains("rsa") {
34 | let ciphertext = client
35 | .asymmetric_encrypt_message_with_rsapkcs1v15(
36 | key.name.clone(),
37 | PLAINTEXT_MESSAGE.to_vec(),
38 | )
39 | .unwrap();
40 | let plaintext = client
41 | .asymmetric_decrypt_message_with_rsapkcs1v15(key.name.clone(), ciphertext)
42 | .unwrap();
43 | assert_eq!(PLAINTEXT_MESSAGE.to_vec(), plaintext);
44 | } else if key.name.contains("ecc") {
45 | let signature = client.sign_with_ecdsa_sha256(key.name.clone(), HASH.to_vec())?;
46 | client.verify_with_ecdsa_sha256(key.name.clone(), HASH.to_vec(), signature)?;
47 | } else {
48 | // If another key than "ecc" or "rsa" is read, it means that the fake mapping was not
49 | // deleted by the provider and this is an error.
50 | panic!(
51 | "The key {} should have been deleted as a fake mapping was created for it.",
52 | key.name
53 | );
54 | }
55 |
56 | if client.is_operation_supported(Opcode::PsaExportKey) {
57 | assert_eq!(
58 | client.export_key(key.name.clone()).unwrap_err(),
59 | ResponseStatus::PsaErrorNotPermitted
60 | );
61 | }
62 | }
63 |
64 | Ok(())
65 | }
66 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | mod key_mappings;
4 | mod normal_tests;
5 | mod stress_test;
6 | #[cfg(feature = "tpm-provider")]
7 | mod tpm_reset;
8 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/normal_tests/auth.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use e2e_tests::auto_test_keyname;
4 | use e2e_tests::TestClient;
5 | use parsec_client::core::interface::requests::{Opcode, ResponseStatus, Result};
6 |
7 | #[test]
8 | fn two_auths_same_key_name() -> Result<()> {
9 | let key_name = auto_test_keyname!();
10 | let mut client = TestClient::new();
11 | let auth1 = String::from("first_client");
12 | let auth2 = String::from("second_client");
13 |
14 | if !client.is_operation_supported(Opcode::PsaGenerateKey) {
15 | return Ok(());
16 | }
17 |
18 | client.set_default_auth(Some(auth1));
19 | #[cfg(not(feature = "cryptoauthlib-provider"))]
20 | client.generate_rsa_sign_key(key_name.clone())?;
21 | #[cfg(feature = "cryptoauthlib-provider")]
22 | client.generate_ecc_key_pair_secpr1_ecdsa_sha256(key_name.clone())?;
23 |
24 | client.set_default_auth(Some(auth2));
25 | #[cfg(not(feature = "cryptoauthlib-provider"))]
26 | let result = client.generate_rsa_sign_key(key_name);
27 | #[cfg(feature = "cryptoauthlib-provider")]
28 | let result = client.generate_ecc_key_pair_secpr1_ecdsa_sha256(key_name);
29 |
30 | result
31 | }
32 |
33 | #[test]
34 | fn delete_wrong_key() -> Result<()> {
35 | let key_name = auto_test_keyname!();
36 | let mut client = TestClient::new();
37 | let auth1 = String::from("first_client");
38 | let auth2 = String::from("second_client");
39 |
40 | if !client.is_operation_supported(Opcode::PsaGenerateKey) {
41 | return Ok(());
42 | }
43 |
44 | client.set_default_auth(Some(auth1));
45 | #[cfg(not(feature = "cryptoauthlib-provider"))]
46 | client.generate_rsa_sign_key(key_name.clone())?;
47 | #[cfg(feature = "cryptoauthlib-provider")]
48 | client.generate_ecc_key_pair_secpr1_ecdsa_sha256(key_name.clone())?;
49 |
50 | client.set_default_auth(Some(auth2));
51 | let status = client
52 | .destroy_key(key_name)
53 | .expect_err("Destroying key should have failed");
54 | assert_eq!(status, ResponseStatus::PsaErrorDoesNotExist);
55 |
56 | Ok(())
57 | }
58 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/normal_tests/generate_random.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use e2e_tests::TestClient;
4 | use parsec_client::core::interface::requests::{Opcode, ResponseStatus};
5 |
6 | #[test]
7 | fn generate_random_not_supported() {
8 | let mut client = TestClient::new();
9 | if !client.is_operation_supported(Opcode::PsaGenerateRandom) {
10 | assert_eq!(
11 | client.generate_bytes(15,).unwrap_err(),
12 | ResponseStatus::PsaErrorNotSupported
13 | );
14 | }
15 | }
16 |
17 | #[test]
18 | fn simple_generate_random() {
19 | let mut client = TestClient::new();
20 |
21 | if !client.is_operation_supported(Opcode::PsaGenerateRandom) {
22 | return;
23 | }
24 |
25 | // Less than one in ~35 billion chance of collision. Should be good enough for our testing.
26 | const NBYTES: usize = 35;
27 | let random_bytes_a = client.generate_bytes(NBYTES).unwrap();
28 | let random_bytes_b = client.generate_bytes(NBYTES).unwrap();
29 |
30 | assert_eq!(random_bytes_a.len(), NBYTES);
31 | assert_eq!(random_bytes_b.len(), NBYTES);
32 |
33 | for (a, b) in random_bytes_a.iter().zip(random_bytes_b.iter()) {
34 | if *a != *b {
35 | return;
36 | }
37 | }
38 |
39 | panic!(
40 | "Two vectors of {} randomly generated bytes were equal!",
41 | NBYTES
42 | );
43 | }
44 |
45 | #[test]
46 | fn generate_zero_bytes() {
47 | let mut client = TestClient::new();
48 |
49 | if !client.is_operation_supported(Opcode::PsaGenerateRandom) {
50 | return;
51 | }
52 |
53 | const NBYTES: usize = 0;
54 | let random_bytes = client.generate_bytes(NBYTES).unwrap();
55 |
56 | assert_eq!(random_bytes, Vec::::new());
57 | }
58 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/normal_tests/hash.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use e2e_tests::TestClient;
4 | use parsec_client::core::interface::operations::psa_algorithm::Hash;
5 | use parsec_client::core::interface::requests::{Opcode, ResponseStatus, Result};
6 |
7 | const MESSAGE: [u8; 14] = [
8 | 0x49, 0x20, 0x61, 0x6d, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
9 | ];
10 | const SHA_256: [u8; 32] = [
11 | 0x0d, 0xc4, 0xbc, 0x13, 0xfd, 0x91, 0x74, 0x52, 0x92, 0x24, 0xc3, 0x8e, 0x0e, 0xe0, 0x75, 0xfa,
12 | 0x9e, 0xd8, 0x0b, 0x78, 0x47, 0xe6, 0xae, 0xa7, 0x6a, 0xe9, 0x8c, 0xf9, 0xdd, 0xd9, 0x26, 0x69,
13 | ];
14 | #[cfg(not(feature = "cryptoauthlib-provider"))]
15 | const RIPE_MD160: [u8; 20] = [
16 | 0xa6, 0xf1, 0xa8, 0xf5, 0x26, 0x04, 0x69, 0xb3, 0x67, 0xa3, 0xae, 0xc6, 0x9f, 0x73, 0x47, 0x9b,
17 | 0xb7, 0xbd, 0x02, 0xb8,
18 | ];
19 | #[cfg(not(feature = "cryptoauthlib-provider"))]
20 | const SHA_512: [u8; 64] = [
21 | 0x54, 0x1f, 0x9e, 0x85, 0xd4, 0xe6, 0xc2, 0x36, 0xf9, 0xb5, 0xef, 0x2e, 0x6d, 0x27, 0xd4, 0x97,
22 | 0x56, 0xda, 0x00, 0xb2, 0x6e, 0xe2, 0x6f, 0xc8, 0x6a, 0x30, 0x47, 0xd3, 0x7f, 0x09, 0xbd, 0xe9,
23 | 0x0a, 0x99, 0x14, 0xf7, 0x3d, 0xf6, 0xe7, 0x01, 0x1c, 0x97, 0x0b, 0x74, 0x84, 0x26, 0xfa, 0x0c,
24 | 0x84, 0x4c, 0xc3, 0xa1, 0x8f, 0x9d, 0x5b, 0x74, 0x01, 0xa4, 0x66, 0x8f, 0x75, 0x73, 0x65, 0xc5,
25 | ];
26 |
27 | #[test]
28 | fn hash_not_supported() {
29 | let mut client = TestClient::new();
30 | if !client.is_operation_supported(Opcode::PsaHashCompute) {
31 | assert_eq!(
32 | client.hash_compute(Hash::Sha256, &[],).unwrap_err(),
33 | ResponseStatus::PsaErrorNotSupported
34 | );
35 | }
36 |
37 | if !client.is_operation_supported(Opcode::PsaHashCompare) {
38 | assert_eq!(
39 | client.hash_compare(Hash::Sha256, &[], &[]).unwrap_err(),
40 | ResponseStatus::PsaErrorNotSupported
41 | );
42 | }
43 | }
44 |
45 | #[test]
46 | fn hash_compute_sha256() {
47 | let mut client = TestClient::new();
48 | if !client.is_operation_supported(Opcode::PsaHashCompute) {
49 | return;
50 | }
51 |
52 | let hash = client.hash_compute(Hash::Sha256, &MESSAGE).unwrap();
53 | assert_eq!(&SHA_256[..], hash.as_slice())
54 | }
55 |
56 | #[cfg(not(feature = "cryptoauthlib-provider"))]
57 | #[test]
58 | fn hash_compute_ripe_md160() {
59 | let mut client = TestClient::new();
60 | if !client.is_operation_supported(Opcode::PsaHashCompute) {
61 | return;
62 | }
63 |
64 | let hash = client.hash_compute(Hash::Ripemd160, &MESSAGE).unwrap();
65 | assert_eq!(&RIPE_MD160[..], hash.as_slice());
66 | }
67 |
68 | #[cfg(not(feature = "cryptoauthlib-provider"))]
69 | #[test]
70 | fn hash_compute_sha512() {
71 | let mut client = TestClient::new();
72 | if !client.is_operation_supported(Opcode::PsaHashCompute) {
73 | return;
74 | }
75 |
76 | let hash = client.hash_compute(Hash::Sha512, &MESSAGE).unwrap();
77 | assert_eq!(&SHA_512[..], hash.as_slice());
78 | }
79 |
80 | #[test]
81 | fn hash_compare_sha256() -> Result<()> {
82 | let mut client = TestClient::new();
83 | if !client.is_operation_supported(Opcode::PsaHashCompare) {
84 | return Ok(());
85 | }
86 |
87 | client.hash_compare(Hash::Sha256, &MESSAGE, &SHA_256)
88 | }
89 |
90 | #[cfg(not(feature = "cryptoauthlib-provider"))]
91 | #[test]
92 | fn hash_compare_ripe_md160() -> Result<()> {
93 | let mut client = TestClient::new();
94 | if !client.is_operation_supported(Opcode::PsaHashCompare) {
95 | return Ok(());
96 | }
97 |
98 | client.hash_compare(Hash::Ripemd160, &MESSAGE, &RIPE_MD160)
99 | }
100 |
101 | #[cfg(not(feature = "cryptoauthlib-provider"))]
102 | #[test]
103 | fn hash_compare_sha512() -> Result<()> {
104 | let mut client = TestClient::new();
105 | if !client.is_operation_supported(Opcode::PsaHashCompare) {
106 | return Ok(());
107 | }
108 |
109 | client.hash_compare(Hash::Sha512, &MESSAGE, &SHA_512)
110 | }
111 |
112 | #[test]
113 | fn hash_compare_false() {
114 | let mut client = TestClient::new();
115 | if !client.is_operation_supported(Opcode::PsaHashCompare) {
116 | return;
117 | }
118 |
119 | let _ = client
120 | .hash_compare(Hash::Sha512, &MESSAGE, &SHA_256)
121 | .unwrap_err();
122 | }
123 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/normal_tests/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | mod aead;
4 | mod asym_encryption;
5 | mod asym_sign_verify;
6 | mod auth;
7 | mod basic;
8 | mod capability_discovery;
9 | mod cipher;
10 | mod create_destroy_key;
11 | mod export_key;
12 | mod export_public_key;
13 | mod generate_random;
14 | mod hash;
15 | mod import_key;
16 | mod key_agreement;
17 | mod key_attestation;
18 | mod key_attributes;
19 | mod ping;
20 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/normal_tests/ping.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use e2e_tests::RequestClient;
4 | use e2e_tests::TestClient;
5 | use parsec_client::core::interface::requests::request::{Request, RequestAuth, RequestBody};
6 | use parsec_client::core::interface::requests::Opcode;
7 | use parsec_client::core::interface::requests::ProviderId;
8 | use parsec_client::core::interface::requests::ResponseStatus;
9 | use parsec_client::core::interface::requests::Result;
10 | use parsec_client::core::ipc_handler::unix_socket;
11 | use std::env;
12 | use std::time::Duration;
13 |
14 | #[test]
15 | fn test_ping() -> Result<()> {
16 | let mut client = TestClient::new();
17 | let version = client.ping()?;
18 | assert_eq!(version.0, 1);
19 | assert_eq!(version.1, 0);
20 |
21 | Ok(())
22 | }
23 |
24 | #[test]
25 | fn mangled_ping() {
26 | let socket_path = env::var("PARSEC_SERVICE_ENDPOINT")
27 | .unwrap_or_else(|_| "/tmp/parsec.sock".into())
28 | .replace("unix:", "");
29 | let client = RequestClient {
30 | ipc_handler: Box::from(
31 | unix_socket::Handler::new(socket_path.into(), Some(Duration::from_secs(1))).unwrap(),
32 | ),
33 | ..Default::default()
34 | };
35 | let mut req = Request::new();
36 | req.header.provider = ProviderId::Core;
37 | req.header.opcode = Opcode::Ping;
38 | req.auth = RequestAuth::new(Vec::from("root"));
39 |
40 | req.body = RequestBody::_from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55]);
41 |
42 | let resp = client
43 | .process_request(req)
44 | .expect("Failed to read Response");
45 | assert_eq!(resp.header.status, ResponseStatus::DeserializingBodyFailed);
46 | }
47 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/stress_test.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use e2e_tests::stress::{StressClient, StressTestConfig};
4 | use std::time::Duration;
5 |
6 | #[test]
7 | fn stress_test() {
8 | let config = StressTestConfig {
9 | no_threads: num_cpus::get(),
10 | req_per_thread: 250,
11 | req_interval: Some(Duration::from_millis(10)),
12 | req_interval_deviation_millis: Some(4),
13 | check_interval: Some(Duration::from_millis(500)),
14 | };
15 |
16 | StressClient::execute(config);
17 | }
18 |
--------------------------------------------------------------------------------
/e2e_tests/tests/per_provider/tpm_reset.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // These tests track a potential regression where the TPM provider
5 | // was unable to handle stored keys after a TPM reset.
6 | //
7 | // `before_tpm_reset` creates keys that should be usable post-TPM-reset,
8 | // in `after_tpm_reset`.
9 | //
10 | // See: https://github.com/parallaxsecond/parsec/issues/504
11 | use e2e_tests::TestClient;
12 |
13 | const RSA_KEY_NAME: &str = "tpm-reset-rsa";
14 | const ECC_KEY_NAME: &str = "tpm-reset-ecc";
15 |
16 | #[test]
17 | fn before_tpm_reset() {
18 | let mut client = TestClient::new();
19 | client.do_not_destroy_keys();
20 |
21 | let rsa_key_name = String::from(RSA_KEY_NAME);
22 | let ecc_key_name = String::from(ECC_KEY_NAME);
23 |
24 | client.generate_rsa_sign_key(rsa_key_name).unwrap();
25 | client
26 | .generate_ecc_key_pair_secpr1_ecdsa_sha256(ecc_key_name)
27 | .unwrap();
28 | }
29 |
30 | #[test]
31 | fn after_tpm_reset() {
32 | let mut client = TestClient::new();
33 |
34 | let rsa_key_name = String::from(RSA_KEY_NAME);
35 | let ecc_key_name = String::from(ECC_KEY_NAME);
36 |
37 | let _ = client
38 | .sign_with_rsa_sha256(rsa_key_name, vec![0xff; 32])
39 | .unwrap();
40 | let _ = client
41 | .sign_with_ecdsa_sha256(ecc_key_name, vec![0xff; 32])
42 | .unwrap();
43 | }
44 |
--------------------------------------------------------------------------------
/fuzz.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | FUZZ_CONTAINER_NAME=parsec_fuzzer
7 | CLEANUP_CONTAINER_NAME=parsec_fuzzer_cleanup
8 |
9 | set -e
10 |
11 | if [[ "$1" == "run" ]]
12 | then
13 | # Set up fuzz folder
14 | docker run --rm -v $(pwd):/parsec -w /parsec/fuzz --name $CLEANUP_CONTAINER_NAME ghcr.io/parallaxsecond/parsec-service-test-all ./cleanup.sh
15 | # A copy of the config file is used because the file is modified during the run
16 | cp fuzz/config.toml fuzz/run_config.toml
17 |
18 | # Stop previous container and run fuzzer
19 | docker kill $FUZZ_CONTAINER_NAME || true
20 | sleep 5s
21 | docker run -d --rm -v $(pwd):/parsec -w /parsec/fuzz --name $FUZZ_CONTAINER_NAME ghcr.io/parallaxsecond/parsec-service-test-all ./run_fuzz.sh
22 | elif [[ "$1" == "stop" ]]
23 | then
24 | docker kill $FUZZ_CONTAINER_NAME
25 | elif [[ "$1" == "follow" ]]
26 | then
27 | docker logs -f --tail 100 $FUZZ_CONTAINER_NAME
28 | elif [[ "$1" == "clean" ]]
29 | then
30 | # Cleanup is done via Docker because on some systems ACL settings prevent the user who
31 | # created a container from removing the files created by said container. Another one
32 | # is needed to do the cleanup.
33 | docker run -d --rm -v $(pwd):/parsec -w /parsec/fuzz --name $CLEANUP_CONTAINER_NAME ghcr.io/parallaxsecond/parsec-service-test-all ./cleanup.sh
34 | elif [[ "$1" == "erase" ]]
35 | then
36 | docker run -d --rm -v $(pwd):/parsec -w /parsec/fuzz -e "ERASE=true" --name $CLEANUP_CONTAINER_NAME ghcr.io/parallaxsecond/parsec-service-test-all ./cleanup.sh
37 | elif [[ "$1" == "test" ]]
38 | then
39 | if [[ -z "$CONTAINER_TAG" ]]
40 | then
41 | CONTAINER_TAG=ghcr.io/parallaxsecond/parsec-service-test-all
42 | fi
43 | # A copy of the config file is used because the file is modified during the run
44 | cp fuzz/config.toml fuzz/run_config.toml
45 | # Run the fuzzer in test mode
46 | docker run --rm -v $(pwd):/parsec -w /parsec/fuzz --name $FUZZ_CONTAINER_NAME $CONTAINER_TAG ./run_fuzz.sh test
47 | else
48 | echo "usage: ./fuzz.sh [COMMAND]
49 |
50 | Commands:
51 | 'run' - builds the fuzzing container and runs the fuzzer
52 | 'stop' - stops the fuzzing container
53 | 'follow' - prints and follows the log output of the fuzzing container
54 | 'clean' - clean up the fuzzing environment (does not remove artifacts or the fuzz corpus)
55 | 'erase' - fully clean the fuzzing environment - WARNING: this will remove all the results of previous runs"
56 | fi
57 |
--------------------------------------------------------------------------------
/fuzz/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | target
3 | corpus
4 | artifacts
5 | *.log
6 | run_config.toml
7 | NVChip
8 | init_corpus
9 |
--------------------------------------------------------------------------------
/fuzz/Cargo.toml:
--------------------------------------------------------------------------------
1 |
2 | [package]
3 | name = "parsec-fuzz"
4 | version = "0.0.0"
5 | authors = ["Ionut Mihalcea ",
6 | "Hugues de Valon "]
7 | publish = false
8 | edition = "2018"
9 |
10 | [package.metadata]
11 | cargo-fuzz = true
12 |
13 | [dependencies]
14 | parsec-service = { path = "..", features = ["mbed-crypto-provider", "pkcs11-provider", "tpm-provider", "direct-authenticator"] }
15 | libfuzzer-sys = "0.3.0"
16 | flexi_logger = "0.14.5"
17 | log = "0.4.8"
18 | toml = "0.8.0"
19 | lazy_static = "1.4.0"
20 | arbitrary = { version = "0.4.0", features = ["derive"] }
21 |
22 | [build-dependencies]
23 | parsec-client = { version = "0.16.0", features = ["testing", "spiffe-auth"] }
24 |
25 | # Prevent this from interfering with workspaces
26 | [workspace]
27 | members = ["."]
28 |
29 | [[bin]]
30 | name = "fuzz_service"
31 | path = "fuzz_targets/fuzz_service.rs"
32 |
33 | [features]
34 | mbed-crypto-provider = []
35 | tpm-provider = []
36 | pkcs11-provider = []
37 |
--------------------------------------------------------------------------------
/fuzz/cleanup.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | rm -f NVChip *log run_config.toml *psa_its
7 | rm -rf mappings
8 | if [[ "$ERASE" == "true" ]]
9 | then
10 | rm -rf artifacts corpus
11 | fi
12 |
--------------------------------------------------------------------------------
/fuzz/config.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 |
3 | [listener]
4 | listener_type = "DomainSocket"
5 | timeout = 200 # in milliseconds
6 | socket_path = "/tmp/parsec.sock"
7 |
8 | [authenticator]
9 | auth_type = "Direct"
10 |
11 | [[key_manager]]
12 | name = "on-disk-manager"
13 | manager_type = "OnDisk"
14 | store_path = "./mappings"
15 |
16 | # [[provider]]
17 | # provider_type = "MbedCryptoProvider"
18 | # key_info_manager = "on-disk-manager"
19 |
20 | [[provider]]
21 | provider_type = "Tpm"
22 | key_info_manager = "on-disk-manager"
23 | tcti = "mssim"
24 | owner_hierarchy_auth = ""
25 |
26 | # [[provider]]
27 | # provider_type = "Pkcs11Provider"
28 | # key_info_manager = "on-disk-manager"
29 | # library_path = "/usr/local/lib/softhsm/libsofthsm2.so"
30 | # user_pin = "123456"
31 | # The slot_number mandatory field is going to be added by the find_slot_number.sh script
32 | # to the last line of this file in the form:
33 | # slot_number = 123456
34 |
--------------------------------------------------------------------------------
/fuzz/fuzz_targets/fuzz_service.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | #![no_main]
4 |
5 | use arbitrary::Arbitrary;
6 | use lazy_static::lazy_static;
7 | use libfuzzer_sys::fuzz_target;
8 | use parsec_service::front::{front_end::FrontEndHandler, listener::Connection};
9 | use parsec_service::utils::{config::ServiceConfig, ServiceBuilder};
10 | use std::cmp;
11 | use std::io::{Read, Result, Write};
12 |
13 | lazy_static! {
14 | static ref FRONT_END_HANDLER: FrontEndHandler = {
15 | log_setup();
16 | let config_file = String::from("./run_config.toml");
17 | let config_file =
18 | std::fs::read_to_string(config_file).expect("Failed to read configuration file");
19 | let config: ServiceConfig =
20 | toml::from_str(&config_file).expect("Failed to parse service configuration");
21 | ServiceBuilder::build_service(&config).expect("Failed to initialize service")
22 | };
23 | }
24 |
25 | #[derive(Arbitrary, Debug)]
26 | struct MockStream(Vec);
27 |
28 | impl Read for MockStream {
29 | fn read(&mut self, buf: &mut [u8]) -> Result {
30 | if self.0.is_empty() {
31 | return Ok(0);
32 | }
33 | let n = cmp::min(buf.len(), self.0.len());
34 | for (idx, val) in self.0.drain(0..n).enumerate() {
35 | buf[idx] = val;
36 | }
37 |
38 | Ok(n)
39 | }
40 | }
41 |
42 | impl Write for MockStream {
43 | fn write(&mut self, buf: &[u8]) -> Result {
44 | Ok(buf.len())
45 | }
46 |
47 | fn flush(&mut self) -> Result<()> {
48 | Ok(())
49 | }
50 | }
51 |
52 | fuzz_target!(|stream: MockStream| {
53 | FRONT_END_HANDLER.handle_request(Connection {
54 | stream: Box::from(stream),
55 | metadata: None,
56 | });
57 | });
58 |
59 | fn log_setup() {
60 | use flexi_logger::writers::FileLogWriter;
61 | use flexi_logger::{LevelFilter, LogSpecBuilder, LogTarget, Logger};
62 |
63 | let flw = FileLogWriter::builder()
64 | .suppress_timestamp()
65 | .directory("./")
66 | .try_build()
67 | .expect("Failed to build FileLogWriter");
68 |
69 | let log_spec = LogSpecBuilder::new().default(LevelFilter::Warn).build();
70 |
71 | Logger::with(log_spec)
72 | .log_target(LogTarget::Writer(Box::from(flw)))
73 | .start()
74 | .unwrap();
75 | }
76 |
--------------------------------------------------------------------------------
/fuzz/run_fuzz.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2020 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | set -ex
7 |
8 | # Use the newest version of the Rust toolchain
9 | rustup update
10 |
11 | # The clean up procedure is called when the script finished or is interrupted
12 | cleanup () {
13 | # Stop tpm_server if running
14 | if [ -n "$TPM_SRV_PID" ]; then kill $TPM_SRV_PID || true; fi
15 | # Remove fake mapping and temp files
16 | rm -rf "mappings"
17 | rm -f "NVChip"
18 | rm -rf *psa_its
19 | }
20 |
21 | trap cleanup EXIT
22 |
23 | setup_tpm() {
24 | # Start TPM server
25 | tpm_server &
26 | TPM_SRV_PID=$!
27 | sleep 5
28 | tpm2_startup -c -T mssim
29 | }
30 |
31 | # Install fuzzer
32 | cargo install cargo-fuzz
33 | # Fuzzer needs nightly toolchain to run
34 | rustup toolchain install nightly
35 |
36 | setup_tpm
37 |
38 | # Find PKCS 11 slot number
39 | CONFIG_PATH="run_config.toml"
40 | # This command suppose that the slot created by the container will be the first one that appears
41 | # when printing all the available slots.
42 | SLOT_NUMBER=`softhsm2-util --show-slots | head -n2 | tail -n1 | cut -d " " -f 2`
43 | # Find all TOML files in the directory (except Cargo.toml) and replace the commented slot number with the valid one
44 | sed -i "s/^# slot_number.*$/slot_number = $SLOT_NUMBER/" $CONFIG_PATH
45 |
46 | # Create corpus if it doesn't exist
47 | cargo build --features="mbed-crypto-provider,tpm-provider,pkcs11-provider"
48 | mkdir -p corpus/fuzz_service
49 | cp init_corpus/* corpus/fuzz_service
50 |
51 |
52 | if [[ "$1" == "test" ]]
53 | then
54 | # Create an artifact from one of the initial corpus entries
55 | mkdir -p artifacts/fuzz_service
56 | cp init_corpus/example-create-ecdsa-key-MbedCrypto artifacts/fuzz_service/
57 | # Run the fuzzer with the artifact just created; if it fails, the whole build should fail
58 | cargo +nightly fuzz run --features="mbed-crypto-provider,tpm-provider,pkcs11-provider" fuzz_service artifacts/fuzz_service/example-create-ecdsa-key-MbedCrypto
59 | exit 0
60 | fi
61 |
62 | set +e
63 |
64 | while [ true ]
65 | do
66 | # Run fuzzer
67 | cargo +nightly fuzz run --features="mbed-crypto-provider,tpm-provider,pkcs11-provider" fuzz_service
68 |
69 | cleanup
70 | setup_tpm
71 |
72 | # Notify about crash
73 | echo "Here we'd ping the webhook to notify"
74 | done
75 |
--------------------------------------------------------------------------------
/quickstart/config.toml:
--------------------------------------------------------------------------------
1 | # See https://parallaxsecond.github.io/parsec-book/parsec_service/configuration.html for a full
2 | # example.
3 |
4 | [core_settings]
5 | log_level = "info"
6 | allow_root = true
7 |
8 | [listener]
9 | listener_type = "DomainSocket"
10 | timeout = 200 # in milliseconds
11 | socket_path = "./parsec.sock"
12 |
13 | [authenticator]
14 | auth_type = "UnixPeerCredentials"
15 |
16 | [[key_manager]]
17 | name = "sqlite-manager"
18 | manager_type = "SQLite"
19 | sqlite_db_path = "./sqlite-key-info-manager.sqlite3"
20 |
21 | [[provider]]
22 | provider_type = "MbedCrypto"
23 | key_info_manager = "sqlite-manager"
24 |
--------------------------------------------------------------------------------
/quickstart/construct-build-details.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2023 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | cat << EOF
7 | ----------------------------------------
8 | -- Parsec Quickstart Build Details
9 | ----------------------------------------
10 | OS: $(cat /build-env/os)
11 | Architecture: $(cat /build-env/arch)
12 | Rust: $(cat /build-env/rustc-version)
13 | Cargo: $(cat /build-env/cargo-version)
14 |
15 | ----------------------------------------
16 | -- Parsec Service
17 | ----------------------------------------
18 | Version: $(cat /build-env/parsec-version)
19 | Commit Hash: $(cat /build-env/parsec-commit)
20 | Dependencies:
21 | $(cat /build-env/parsec-dependencies)
22 |
23 | ----------------------------------------
24 | -- Parsec Tool
25 | ----------------------------------------
26 | Version: $(cat /build-env/parsec-tool-version)
27 | Commit Hash: $(cat /build-env/parsec-tool-commit)
28 | Dependencies:
29 | $(cat /build-env/parsec-tool-dependencies)
30 |
31 | EOF
32 |
--------------------------------------------------------------------------------
/quickstart/package.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2022 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | # Create a quickstart package
7 |
8 | # Avoid silent failures
9 | set -euf -o pipefail
10 |
11 | PACKAGE_PATH=$(pwd)
12 | ASSETS_DIR=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd)
13 | PARSEC_DIR=$(dirname $ASSETS_DIR)
14 |
15 | # Usage
16 | USAGE_STR=\
17 | "Usage:\n"\
18 | "package.sh [Options]\n"\
19 | "Options:\n"\
20 | " -o {path}: Output absolute path, the default path is the current directory i.e. $(pwd)\n"\
21 | " -h : Display this help menu\n"
22 |
23 | # Flags
24 | while getopts v:o:j:h flag
25 | do
26 | case "${flag}" in
27 | o) PACKAGE_PATH=${OPTARG};;
28 | h) echo -e $USAGE_STR; exit 0;;
29 | esac
30 | done
31 |
32 | check_release_tag() {
33 | CURRENT_TAG=$(git name-rev --tags HEAD | cut -d "/" -f 2)
34 | LATTEST_TAG=$(git tag --sort=committerdate | tail -1)
35 | if [ -z "$LATTEST_TAG" ];then
36 | echo "Warning:No tags"
37 | fi
38 | if [ "$LATTEST_TAG" == "$CURRENT_TAG" ]; then
39 | echo "Packaging release tag: $LATTEST_TAG"
40 | else
41 | echo "Warning: The current HEAD doesn't match the latest tagged"
42 | echo "Warning: Please checkout the latest tag : $LATTEST_TAG"
43 | read -n 1 -p "Do you want to continue anyway [y/n]?" choice
44 | if [ "$choice" != "y" ]; then
45 | exit 1
46 | fi
47 | fi
48 | }
49 |
50 | build_runnable_image() {
51 | docker build --target runnable_image --tag parallaxsecond/parsec-quickstart -f quickstart.Dockerfile ${PARSEC_DIR}
52 | }
53 |
54 | build_extract_tarball() {
55 | docker build --target tarball_builder --tag parallaxsecond/parsec-quickstart-tarball -f quickstart.Dockerfile ${PARSEC_DIR}
56 |
57 | # Extract the tarball out of the image used to construct it and place it in ${PACKAGE_PATH}
58 | docker run -v ${PACKAGE_PATH}:/opt/mount --rm parallaxsecond/parsec-quickstart-tarball bash -c 'cp /parsec-tar/*.tar.gz /opt/mount/'
59 | }
60 |
61 | echo "Packaging started..."
62 |
63 | trap EXIT
64 |
65 | check_release_tag
66 | build_runnable_image
67 | build_extract_tarball
68 |
69 | echo "Finalizing packages"
70 |
--------------------------------------------------------------------------------
/quickstart/quickstart.Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2023 Contributors to the Parsec project.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # ---------------------------------------------
5 | # Docker Stage: Base builder used for both parsec service and tools
6 | FROM rust:latest AS base_builder
7 |
8 | RUN apt update -y && \
9 | apt install -y llvm-dev libclang-dev clang cmake jq
10 |
11 | ## Track various build environment things we may want to use throughout
12 | WORKDIR /build-env
13 | RUN echo "$(uname | awk '{print tolower($0)}')" > /build-env/os
14 | RUN echo "$(arch)" > /build-env/arch
15 | RUN echo "$(rustc --version)" > /build-env/rustc-version
16 | RUN echo "$(cargo --version)" > /build-env/cargo-version
17 |
18 | # ---------------------------------------------
19 | # Docker Stage: Temporary stage to help dependency caching
20 | FROM base_builder AS parsec_service_scratch
21 |
22 | ## Copy everything in
23 | COPY . /parsec-service
24 | WORKDIR /parsec-service
25 |
26 | # This just adds cargo dependencies to the scratch stage so that we don't need to
27 | # download them each time the builder runs.
28 | RUN cargo fetch
29 |
30 | # ---------------------------------------------
31 | # Docker Stage: Executes the build of the Parsec Service
32 | FROM parsec_service_scratch AS parsec_service_builder
33 |
34 | ## Run the actual build
35 | RUN cargo build --release --features mbed-crypto-provider
36 |
37 | # Save the current parsec version and dependencies as defined by cargo and the current git commit hash
38 | RUN echo "$(cargo metadata --format-version=1 --no-deps --offline | jq -r '.packages[0].version')" > /build-env/parsec-version
39 | RUN echo "$(cargo tree)" > /build-env/parsec-dependencies
40 | RUN echo "$(git rev-parse HEAD)" > /build-env/parsec-commit
41 |
42 | # ---------------------------------------------
43 | # Docker Stage: Executes the build of the Parsec Tool
44 | FROM base_builder AS parsec_tool_builder
45 |
46 | RUN git clone https://github.com/parallaxsecond/parsec-tool /parsec-tool
47 | WORKDIR /parsec-tool
48 | RUN git checkout $(git tag --sort=committerdate | tail -1)
49 | RUN cargo build --release
50 |
51 | # Save the current parsec-tool version and dependencies as defined by cargo and the current git commit hash
52 | RUN echo "$(cargo metadata --format-version=1 --no-deps --offline | jq -r '.packages[0].version')" > /build-env/parsec-tool-version
53 | RUN echo "$(cargo tree)" > /build-env/parsec-tool-dependencies
54 | RUN echo "$(git rev-parse HEAD)" > /build-env/parsec-tool-commit
55 |
56 | # ---------------------------------------------
57 | # Docker Stage: Extracts build results from previous stages and adds in quickstart configs
58 | FROM base_builder AS layout
59 |
60 | ## Add the built binaries into the image
61 | COPY --from=parsec_service_builder /parsec-service/target/release/parsec /parsec/bin/parsec
62 | COPY --from=parsec_tool_builder /parsec-tool/target/release/parsec-tool /parsec/bin/parsec-tool
63 |
64 | ## Create and configure a starting directory for quickstart operations
65 | WORKDIR /parsec/quickstart
66 | COPY quickstart/config.toml /parsec/quickstart/config.toml
67 | COPY --from=parsec_tool_builder /parsec-tool/tests/parsec-cli-tests.sh /parsec/quickstart/parsec-cli-tests.sh
68 |
69 | ## Grab all the build-env values
70 | COPY --from=parsec_service_builder /build-env/* /build-env/
71 | COPY --from=parsec_tool_builder /build-env/* /build-env/
72 |
73 | ## Generate the build details file
74 | COPY quickstart/construct-build-details.sh /build-env/
75 | RUN chmod +x /build-env/construct-build-details.sh && /build-env/construct-build-details.sh > /parsec/quickstart/build.txt
76 |
77 | # ---------------------------------------------
78 | # Docker Stage: Constructs an appropriate tarball containing all binaries and files
79 | FROM ubuntu:latest AS tarball_builder
80 |
81 | COPY --from=layout /parsec /parsec
82 | COPY quickstart/tarball_README.md /parsec/quickstart/README.md
83 | COPY --from=parsec_service_builder /build-env /build-env
84 |
85 | ## Generate a tarball containing all quickstart items and named using the version, os, and arch
86 | RUN NAME="quickstart-$(cat /build-env/parsec-version)-$(cat /build-env/os)-$(cat /build-env/arch)" \
87 | && mv /parsec ${NAME} \
88 | && mkdir /parsec-tar \
89 | && tar -zcvf /parsec-tar/${NAME}.tar.gz /${NAME}
90 |
91 | # ---------------------------------------------
92 | # Docker Stage: Constructs a valid Docker image with Parsec Quickstart
93 | FROM ubuntu:latest AS runnable_image
94 |
95 | COPY --from=layout /parsec /parsec
96 | COPY quickstart/docker_README.md /parsec/quickstart/README.md
97 |
98 | ENV PATH=$PATH:/parsec/bin
99 | ENV PARSEC_SERVICE_ENDPOINT=unix:/parsec/quickstart/parsec.sock
100 |
101 | RUN apt update && apt install -y openssl
102 |
103 | RUN useradd -ms /bin/bash qs
104 | RUN chown -R qs:qs /parsec/quickstart
105 | USER qs
106 |
107 | WORKDIR /parsec/quickstart
108 |
--------------------------------------------------------------------------------
/src/authenticators/jwt_svid_authenticator/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! JWT SVID authenticator
4 |
5 | use super::{Admin, AdminList, Application, ApplicationIdentity, Authenticate};
6 | use crate::front::listener::ConnectionMetadata;
7 | use log::error;
8 | use parsec_interface::operations::list_authenticators;
9 | use parsec_interface::requests::request::RequestAuth;
10 | use parsec_interface::requests::Result;
11 | use parsec_interface::requests::{AuthType, ResponseStatus};
12 | use parsec_interface::secrecy::ExposeSecret;
13 | use spiffe::workload_api::client::WorkloadApiClient;
14 | use std::str;
15 |
16 | /// JWT SVID authenticator
17 | #[allow(missing_debug_implementations)]
18 | pub struct JwtSvidAuthenticator {
19 | client: WorkloadApiClient,
20 | admins: AdminList,
21 | }
22 |
23 | impl JwtSvidAuthenticator {
24 | /// Create a new JWT-SVID authenticator with a specific path to the Workload API socket.
25 | pub fn new(workload_endpoint: String, admins: Vec) -> Option {
26 | let client = match WorkloadApiClient::new(&workload_endpoint) {
27 | Ok(client) => client,
28 | Err(e) => {
29 | error!("Can't start the SPIFFE Workload API client ({}).", e);
30 | return None;
31 | }
32 | };
33 | Some(JwtSvidAuthenticator {
34 | client,
35 | admins: admins.into(),
36 | })
37 | }
38 | }
39 |
40 | impl Authenticate for JwtSvidAuthenticator {
41 | fn describe(&self) -> Result {
42 | Ok(list_authenticators::AuthenticatorInfo {
43 | description: String::from(
44 | "Authenticator validating a JWT SPIFFE Verifiable Identity Document",
45 | ),
46 | version_maj: 0,
47 | version_min: 1,
48 | version_rev: 0,
49 | id: AuthType::JwtSvid,
50 | })
51 | }
52 |
53 | fn authenticate(
54 | &self,
55 | auth: &RequestAuth,
56 | _: Option,
57 | ) -> Result {
58 | let svid = str::from_utf8(auth.buffer.expose_secret()).map_err(|e| {
59 | error!(
60 | "The authentication buffer can not be parsed into a UTF-8 string ({}).",
61 | e
62 | );
63 | ResponseStatus::InvalidEncoding
64 | })?;
65 |
66 | let jwt_token = self
67 | .client
68 | .validate_jwt_token("parsec", svid)
69 | .map_err(|e| {
70 | error!("The validation of the JWT-SVID failed ({}).", e);
71 | ResponseStatus::AuthenticationError
72 | })?;
73 | let app_name = jwt_token.spiffe_id().to_string();
74 | let is_admin = self.admins.is_admin(&app_name);
75 | Ok(Application {
76 | identity: ApplicationIdentity {
77 | name: app_name,
78 | auth: AuthType::JwtSvid.into(),
79 | },
80 | is_admin,
81 | })
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/back/dispatcher.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! Dispatch requests to the correct backend
4 | //!
5 | //! The dispatcher's role is to direct requests to the provider they specify, if
6 | //! said provider is available on the system, thus acting as a multiplexer.
7 | use super::backend_handler::BackEndHandler;
8 | use crate::authenticators::Application;
9 | use log::trace;
10 | use parsec_interface::requests::request::Request;
11 | use parsec_interface::requests::ProviderId;
12 | use parsec_interface::requests::{Response, ResponseStatus};
13 | use std::collections::HashMap;
14 | use std::io::{Error, ErrorKind, Result};
15 |
16 | /// Dispatcher to backend
17 | ///
18 | /// Component tasked with identifying the backend handler that can
19 | /// service a request.
20 | ///
21 | /// As such, it owns all the backend handlers and attempts to match
22 | /// the fields in the request header to the properties of the handlers.
23 | #[derive(Debug)]
24 | pub struct Dispatcher {
25 | backends: HashMap,
26 | }
27 |
28 | impl Dispatcher {
29 | /// Parses the `provider` field of the request header and attempts to find
30 | /// the backend handler to which the request must be dispatched.
31 | ///
32 | /// Returns either the response coming from the backend handler, or a response
33 | /// containing a status code consistent with the error encountered during
34 | /// processing.
35 | pub fn dispatch_request(&self, request: Request, app: Option) -> Response {
36 | trace!("dispatch_request ingress");
37 | if let Some(backend) = self.backends.get(&request.header.provider) {
38 | if let Err(status) = backend.is_capable(&request) {
39 | Response::from_request_header(request.header, status)
40 | } else {
41 | {
42 | let response = backend.execute_request(request, app);
43 | trace!("execute_request egress");
44 | response
45 | }
46 | }
47 | } else {
48 | Response::from_request_header(request.header, ResponseStatus::ProviderNotRegistered)
49 | }
50 | }
51 | }
52 |
53 | /// `Dispatcher` builder
54 | #[derive(Debug, Default)]
55 | pub struct DispatcherBuilder {
56 | backends: Option>,
57 | }
58 |
59 | impl DispatcherBuilder {
60 | /// Create a new Dispatcher builder
61 | pub fn new() -> Self {
62 | DispatcherBuilder { backends: None }
63 | }
64 |
65 | /// Add a BackEndHandler with a specific Provider ID to the dispatcher
66 | pub fn with_backend(
67 | mut self,
68 | provider_id: ProviderId,
69 | backend_handler: BackEndHandler,
70 | ) -> Self {
71 | let mut backends = self.backends.unwrap_or_default();
72 | let _ = backends.insert(provider_id, backend_handler);
73 | self.backends = Some(backends);
74 |
75 | self
76 | }
77 |
78 | /// Add multiple BackEndHandler to the dispatcher in one call
79 | pub fn with_backends(mut self, new_backends: HashMap) -> Self {
80 | let mut backends = self.backends.unwrap_or_default();
81 | backends.extend(new_backends);
82 | self.backends = Some(backends);
83 |
84 | self
85 | }
86 |
87 | /// Build the builder into a dispatcher
88 | pub fn build(self) -> Result {
89 | Ok(Dispatcher {
90 | backends: self
91 | .backends
92 | .ok_or_else(|| Error::new(ErrorKind::InvalidData, "backends is missing"))?,
93 | })
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/back/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! Routing and parsing requests for processing by providers
4 | pub mod backend_handler;
5 | pub mod dispatcher;
6 |
--------------------------------------------------------------------------------
/src/front/listener.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! Interface for service IPC front
4 | //!
5 | //! The [`Listen`](https://parallaxsecond.github.io/parsec-book/parsec_service/listeners.html)
6 | //! trait acts as an interface for the operations that must be supported by any implementation
7 | //! of the IPC mechanism used as a Parsec front.
8 | use derivative::Derivative;
9 | use std::time::Duration;
10 |
11 | /// This trait is created to allow the iterator returned by incoming to iterate over a trait object
12 | /// that implements both Read and Write.
13 | pub trait ReadWrite: std::io::Read + std::io::Write {}
14 | // Automatically implements ReadWrite for all types that implement Read and Write.
15 | impl ReadWrite for T {}
16 |
17 | /// Specifies metadata associated with a connection, if any.
18 | #[derive(Copy, Clone, Debug)]
19 | pub enum ConnectionMetadata {
20 | /// Unix peer credentials metadata for Unix domain sockets.
21 | UnixPeerCredentials {
22 | /// The effective UID of the connecting process.
23 | uid: u32,
24 | /// The effective GID of the connecting process.
25 | gid: u32,
26 | /// The optional PID of the connecting process. This is an Option because not all
27 | /// platforms support retrieving PID via a domain socket.
28 | pid: Option,
29 | },
30 | // NOTE: there is currently only _one_ variant of the ConnectionMetadata enum. When a second
31 | // variant is added, you will need to update some tests!
32 | // You should grep the tests for `TODO(new_metadata_variant)` and update them accordingly.
33 | }
34 |
35 | /// Represents a connection to a single client
36 | #[derive(Derivative)]
37 | #[derivative(Debug)]
38 | pub struct Connection {
39 | /// Stream used for communication with the client
40 | #[derivative(Debug = "ignore")]
41 | pub stream: Box,
42 | /// Metadata associated with the connection that might be useful elsewhere (i.e. authentication, etc)
43 | pub metadata: Option,
44 | }
45 |
46 | /// IPC front manager interface
47 | ///
48 | /// Interface defining the functionality that any IPC front manager has to expose to Parsec for normal
49 | /// operation.
50 | pub trait Listen {
51 | /// Set the timeout on read and write calls on any stream returned by this listener.
52 | fn set_timeout(&mut self, duration: Duration);
53 |
54 | /// Non-blocking call that gets the next client connection and returns a stream
55 | /// (a Read and Write trait object). Requests are read from the stream and responses are written
56 | /// to it. Streams returned by this method should have a timeout period as set by the
57 | /// `set_timeout` method.
58 | /// If no connections are present, return `None`.
59 | /// If there are any errors in establishing the connection other than the missing
60 | /// initialization, the implementation should log them and return `None`.
61 | /// `Send` is needed because the stream is moved to a thread.
62 | ///
63 | /// # Panics
64 | ///
65 | /// If the listener has not been initialised before, with the `init` method.
66 | fn accept(&self) -> Option;
67 | }
68 |
--------------------------------------------------------------------------------
/src/front/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! IPC front handlers
4 | pub mod domain_socket;
5 | pub mod front_end;
6 | pub mod listener;
7 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! Parsec service documentation
4 | //!
5 | //! This is the source code documentation for Parsec (Platform AbstRaction for
6 | //! SECurity) service. For a more in-depth guide of the system architecture,
7 | //! supported operations and other Parsec-related topics, see our
8 | //! [Parsec Book](https://parallaxsecond.github.io/parsec-book/index.html).
9 | #![deny(
10 | nonstandard_style,
11 | dead_code,
12 | improper_ctypes,
13 | non_shorthand_field_patterns,
14 | no_mangle_generic_items,
15 | overflowing_literals,
16 | path_statements,
17 | patterns_in_fns_without_body,
18 | unconditional_recursion,
19 | unused,
20 | unused_allocation,
21 | unused_comparisons,
22 | unused_parens,
23 | while_true,
24 | missing_debug_implementations,
25 | missing_docs,
26 | trivial_casts,
27 | trivial_numeric_casts,
28 | unused_extern_crates,
29 | unused_import_braces,
30 | unused_qualifications,
31 | unused_results,
32 | missing_copy_implementations
33 | )]
34 | // This one is hard to avoid.
35 | #![allow(clippy::multiple_crate_versions)]
36 |
37 | #[allow(unused)]
38 | macro_rules! format_error {
39 | ($message:expr, $error:expr) => {
40 | if crate::utils::GlobalConfig::log_error_details() {
41 | log::error!("{}; Error: {}", $message, $error)
42 | } else {
43 | log::error!("{};", $message)
44 | }
45 | };
46 | }
47 |
48 | #[allow(unused)]
49 | macro_rules! deprecation_check {
50 | ($operation:ident, $warning:expr, $return_flag:expr) => {
51 | if let Err(ResponseStatus::DeprecatedPrimitive) = $operation.check_deprecated() {
52 | log::warn!("{}", $warning);
53 | if $return_flag && !crate::utils::GlobalConfig::allow_deprecated() {
54 | return Err(ResponseStatus::DeprecatedPrimitive);
55 | }
56 | }
57 | };
58 | }
59 |
60 | #[allow(unused)]
61 | macro_rules! warn_on_deprecated {
62 | ($operation:ident, $warning:expr) => {
63 | deprecation_check!($operation, $warning, false);
64 | };
65 | }
66 |
67 | #[allow(unused)]
68 | macro_rules! return_on_deprecated {
69 | ($operation:ident, $warning:expr) => {
70 | deprecation_check!($operation, $warning, true);
71 | };
72 | }
73 |
74 | pub mod authenticators;
75 | pub mod back;
76 | pub mod front;
77 | pub mod key_info_managers;
78 | pub mod providers;
79 | pub mod utils;
80 |
--------------------------------------------------------------------------------
/src/providers/cryptoauthlib/access_keys.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use log::{error, warn};
5 | use serde::Deserialize;
6 | use std::fs::read_to_string;
7 | use std::path::Path;
8 |
9 | #[derive(Debug, Deserialize)]
10 | struct AccessKeyContainer {
11 | access_keys: Vec,
12 | }
13 |
14 | #[derive(Debug, Deserialize)]
15 | struct AccessKey {
16 | slot: u8,
17 | key: [u8; 32],
18 | }
19 |
20 | impl Provider {
21 | /// Read access keys from a configuration file and setup the CALib to use them.
22 | pub fn set_access_keys(
23 | &self,
24 | access_keys_file_name: Option,
25 | ) -> Option {
26 | let access_keys_string = match access_keys_file_name.clone() {
27 | None => {
28 | warn!("Missing 'access_key_file_name' entry in configuration toml file");
29 | return None;
30 | }
31 | Some(file_name) => match read_to_string(Path::new(&file_name)) {
32 | Err(err) => {
33 | warn!("Cannot read from {} file because: {}.", file_name, err);
34 | return None;
35 | }
36 | Ok(config_string) => config_string,
37 | },
38 | };
39 | let access_keys_container: AccessKeyContainer = match toml::from_str(&access_keys_string) {
40 | Ok(keys) => keys,
41 | Err(err) => {
42 | error!(
43 | "Error parsing access key config file {}. {}",
44 | access_keys_file_name.unwrap(),
45 | err
46 | );
47 | return None;
48 | }
49 | };
50 | for access_key in access_keys_container.access_keys.iter() {
51 | if rust_cryptoauthlib::ATCA_ATECC_SLOTS_COUNT > access_key.slot {
52 | let err = self.device.add_access_key(access_key.slot, &access_key.key);
53 | match err {
54 | rust_cryptoauthlib::AtcaStatus::AtcaSuccess => (),
55 | _ => error!(
56 | "add_access_key() for slot {} failed, because {}",
57 | access_key.slot, err
58 | ),
59 | }
60 | } else {
61 | error!(
62 | "add_access_key() for slot {} failed, because it exceeded total slots count {}",
63 | access_key.slot,
64 | rust_cryptoauthlib::ATCA_ATECC_SLOTS_COUNT
65 | )
66 | }
67 | }
68 |
69 | Some(rust_cryptoauthlib::AtcaStatus::AtcaSuccess)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/providers/cryptoauthlib/generate_random.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use parsec_interface::operations::psa_generate_random;
5 | use parsec_interface::requests::{ResponseStatus, Result};
6 |
7 | impl Provider {
8 | pub(super) fn psa_generate_random_internal(
9 | &self,
10 | op: psa_generate_random::Operation,
11 | ) -> Result {
12 | let mut random_bytes = vec![0u8; 0];
13 | let zero_vector = vec![0u8, op.size as u8];
14 | let mut loop_count = 0u8;
15 | // external loop to retry generation if vector is not secure
16 | loop {
17 | // calculate internal loop count
18 | let call_count = (op.size + rust_cryptoauthlib::ATCA_RANDOM_BUFFER_SIZE - 1)
19 | / rust_cryptoauthlib::ATCA_RANDOM_BUFFER_SIZE;
20 | // internal loop for vector size greater than buffer size
21 | for _i in 0..call_count {
22 | let mut buffer = Vec::with_capacity(rust_cryptoauthlib::ATCA_RANDOM_BUFFER_SIZE);
23 | let err = self.device.random(&mut buffer);
24 | match err {
25 | rust_cryptoauthlib::AtcaStatus::AtcaSuccess => {
26 | // append buffer vector to result vector
27 | random_bytes.append(&mut buffer);
28 | }
29 | _ => {
30 | let error = ResponseStatus::PsaErrorGenericError;
31 | format_error!("Bytes generation failed ", err);
32 | return Err(error);
33 | }
34 | }
35 | } // end internal loop
36 | random_bytes.truncate(op.size); // cut vector to desired size
37 | match random_bytes != zero_vector {
38 | true => {
39 | break Ok(psa_generate_random::Result {
40 | random_bytes: random_bytes.into(),
41 | })
42 | }
43 | false => {
44 | loop_count += 1;
45 | if loop_count < 3 {
46 | continue;
47 | } else {
48 | let err = ResponseStatus::PsaErrorInsufficientEntropy;
49 | format_error!("Bytes generation failed ", err);
50 | return Err(err);
51 | }
52 | }
53 | }
54 | } // end external loop
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/providers/cryptoauthlib/hash.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use log::error;
5 | use parsec_interface::operations::psa_algorithm::Hash;
6 | use parsec_interface::operations::psa_hash_compare;
7 | use parsec_interface::operations::psa_hash_compute;
8 | use parsec_interface::requests::{ResponseStatus, Result};
9 |
10 | impl Provider {
11 | /// Calculate SHA2-256 digest for a given message using CALib.
12 | /// Ensure proper return value type.
13 | pub fn sha256(&self, msg: &[u8]) -> Result {
14 | let mut hash = vec![0u8; rust_cryptoauthlib::ATCA_SHA2_256_DIGEST_SIZE];
15 | let result = self.device.sha(msg.to_vec(), &mut hash);
16 | match result {
17 | rust_cryptoauthlib::AtcaStatus::AtcaSuccess => {
18 | Ok(psa_hash_compute::Result { hash: hash.into() })
19 | }
20 | _ => {
21 | error!("Hash compute failed, hardware reported: {}.", result);
22 | Err(ResponseStatus::PsaErrorHardwareFailure)
23 | }
24 | }
25 | }
26 |
27 | pub(super) fn psa_hash_compute_internal(
28 | &self,
29 | op: psa_hash_compute::Operation,
30 | ) -> Result {
31 | match op.alg {
32 | Hash::Sha256 => self.sha256(&op.input),
33 | _ => Err(ResponseStatus::PsaErrorNotSupported),
34 | }
35 | }
36 |
37 | pub(super) fn psa_hash_compare_internal(
38 | &self,
39 | op: psa_hash_compare::Operation,
40 | ) -> Result {
41 | // check hash length
42 | if op.hash.len() != Hash::Sha256.hash_length() {
43 | error!("Invalid input hash length.");
44 | return Err(ResponseStatus::PsaErrorInvalidArgument);
45 | }
46 | match op.alg {
47 | Hash::Sha256 => {
48 | // compute hash
49 | let hash = self.sha256(&op.input)?.hash;
50 | // compare input vs. computed hash
51 | if op.hash != hash {
52 | error!("Hash comparison failed.");
53 | Err(ResponseStatus::PsaErrorInvalidSignature)
54 | } else {
55 | Ok(psa_hash_compare::Result)
56 | }
57 | }
58 | _ => Err(ResponseStatus::PsaErrorNotSupported),
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/providers/cryptoauthlib/key_agreement.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use parsec_interface::operations::psa_algorithm::RawKeyAgreement;
7 | use parsec_interface::operations::psa_raw_key_agreement;
8 | use parsec_interface::requests::{ResponseStatus, Result};
9 | use parsec_interface::secrecy::Secret;
10 |
11 | impl Provider {
12 | pub(super) fn psa_raw_key_agreement_internal(
13 | &self,
14 | application_identity: &ApplicationIdentity,
15 | op: psa_raw_key_agreement::Operation,
16 | ) -> Result {
17 | let key_identity = KeyIdentity::new(
18 | application_identity.clone(),
19 | self.provider_identity.clone(),
20 | op.private_key_name.clone(),
21 | );
22 | let key_id = self.key_info_store.get_key_id::(&key_identity)?;
23 | let key_attributes = self.key_info_store.get_key_attributes(&key_identity)?;
24 | op.validate(key_attributes)?;
25 |
26 | match op.alg {
27 | RawKeyAgreement::Ecdh => {
28 | let parameters = rust_cryptoauthlib::EcdhParams {
29 | out_target: rust_cryptoauthlib::EcdhTarget::Output,
30 | slot_id: Some(key_id),
31 | ..Default::default()
32 | };
33 | let mut key_data = op.peer_key.to_vec();
34 | if key_data.len() == 65 {
35 | key_data = op.peer_key[1..].to_vec();
36 | }
37 | match self.device.ecdh(parameters, &key_data) {
38 | Ok(result) => {
39 | let shared_secret = result.pms.unwrap().to_vec();
40 | Ok(psa_raw_key_agreement::Result {
41 | shared_secret: Secret::new(shared_secret),
42 | })
43 | }
44 | Err(status) => {
45 | format_error!("Raw key agreement status: ", status);
46 | Err(ResponseStatus::PsaErrorGenericError)
47 | }
48 | }
49 | }
50 | _ => Err(ResponseStatus::PsaErrorNotSupported),
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/providers/mbed_crypto/aead.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use parsec_interface::operations::{psa_aead_decrypt, psa_aead_encrypt};
7 | use parsec_interface::requests::{ResponseStatus, Result};
8 | use psa_crypto::operations::aead;
9 | use psa_crypto::types::key;
10 |
11 | impl Provider {
12 | pub(super) fn psa_aead_encrypt_internal(
13 | &self,
14 | application_identity: &ApplicationIdentity,
15 | op: psa_aead_encrypt::Operation,
16 | ) -> Result {
17 | let key_name = op.key_name.clone();
18 |
19 | let key_identity = KeyIdentity::new(
20 | application_identity.clone(),
21 | self.provider_identity.clone(),
22 | key_name,
23 | );
24 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
25 | let _guard = self
26 | .key_handle_mutex
27 | .lock()
28 | .expect("Grabbing key handle mutex failed");
29 | let id = key::Id::from_persistent_key_id(key_id)?;
30 | let key_attributes = key::Attributes::from_key_id(id)?;
31 |
32 | op.validate(key_attributes)?;
33 | let alg = op.alg;
34 | let buffer_size = key_attributes.aead_encrypt_output_size(alg, op.plaintext.len())?;
35 | let mut ciphertext = vec![0u8; buffer_size];
36 |
37 | match aead::encrypt(
38 | id,
39 | alg,
40 | &op.nonce,
41 | &op.additional_data,
42 | &op.plaintext,
43 | &mut ciphertext,
44 | ) {
45 | Ok(output_size) => {
46 | ciphertext.resize(output_size, 0);
47 | Ok(psa_aead_encrypt::Result {
48 | ciphertext: ciphertext.into(),
49 | })
50 | }
51 | Err(error) => {
52 | let error = ResponseStatus::from(error);
53 | format_error!("Encrypt status: ", error);
54 | Err(error)
55 | }
56 | }
57 | }
58 |
59 | pub(super) fn psa_aead_decrypt_internal(
60 | &self,
61 | application_identity: &ApplicationIdentity,
62 | op: psa_aead_decrypt::Operation,
63 | ) -> Result {
64 | let key_identity = KeyIdentity::new(
65 | application_identity.clone(),
66 | self.provider_identity.clone(),
67 | op.key_name.clone(),
68 | );
69 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
70 |
71 | let _guard = self
72 | .key_handle_mutex
73 | .lock()
74 | .expect("Grabbing key handle mutex failed");
75 |
76 | let id = key::Id::from_persistent_key_id(key_id)?;
77 | let key_attributes = key::Attributes::from_key_id(id)?;
78 | op.validate(key_attributes)?;
79 | let buffer_size = key_attributes.aead_decrypt_output_size(op.alg, op.ciphertext.len())?;
80 | let mut plaintext = vec![0u8; buffer_size];
81 |
82 | match aead::decrypt(
83 | id,
84 | op.alg,
85 | &op.nonce,
86 | &op.additional_data,
87 | &op.ciphertext,
88 | &mut plaintext,
89 | ) {
90 | Ok(output_size) => {
91 | plaintext.resize(output_size, 0);
92 | Ok(psa_aead_decrypt::Result {
93 | plaintext: plaintext.into(),
94 | })
95 | }
96 | Err(error) => {
97 | let error = ResponseStatus::from(error);
98 | format_error!("Decrypt status: ", error);
99 | Err(error)
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/providers/mbed_crypto/asym_encryption.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use parsec_interface::operations::{psa_asymmetric_decrypt, psa_asymmetric_encrypt};
7 | use parsec_interface::requests::{ResponseStatus, Result};
8 | use psa_crypto::operations::asym_encryption;
9 | use psa_crypto::types::key;
10 |
11 | impl Provider {
12 | pub(super) fn psa_asymmetric_encrypt_internal(
13 | &self,
14 | application_identity: &ApplicationIdentity,
15 | op: psa_asymmetric_encrypt::Operation,
16 | ) -> Result {
17 | let key_name = op.key_name.clone();
18 |
19 | let key_identity = KeyIdentity::new(
20 | application_identity.clone(),
21 | self.provider_identity.clone(),
22 | key_name,
23 | );
24 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
25 | let _guard = self
26 | .key_handle_mutex
27 | .lock()
28 | .expect("Grabbing key handle mutex failed");
29 | let id = key::Id::from_persistent_key_id(key_id)?;
30 | let key_attributes = key::Attributes::from_key_id(id)?;
31 |
32 | op.validate(key_attributes)?;
33 | let salt_buff = op.salt.as_ref().map(|salt| salt.as_slice());
34 | let alg = op.alg;
35 | let buffer_size = key_attributes.asymmetric_encrypt_output_size(alg)?;
36 | let mut ciphertext = vec![0u8; buffer_size];
37 |
38 | match asym_encryption::encrypt(id, alg, &op.plaintext, salt_buff, &mut ciphertext) {
39 | Ok(output_size) => {
40 | ciphertext.resize(output_size, 0);
41 | Ok(psa_asymmetric_encrypt::Result {
42 | ciphertext: ciphertext.into(),
43 | })
44 | }
45 | Err(error) => {
46 | let error = ResponseStatus::from(error);
47 | format_error!("Encrypt status: ", error);
48 | Err(error)
49 | }
50 | }
51 | }
52 |
53 | pub(super) fn psa_asymmetric_decrypt_internal(
54 | &self,
55 | application_identity: &ApplicationIdentity,
56 | op: psa_asymmetric_decrypt::Operation,
57 | ) -> Result {
58 | let key_identity = KeyIdentity::new(
59 | application_identity.clone(),
60 | self.provider_identity.clone(),
61 | op.key_name.clone(),
62 | );
63 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
64 |
65 | let _guard = self
66 | .key_handle_mutex
67 | .lock()
68 | .expect("Grabbing key handle mutex failed");
69 |
70 | let id = key::Id::from_persistent_key_id(key_id)?;
71 | let key_attributes = key::Attributes::from_key_id(id)?;
72 | op.validate(key_attributes)?;
73 | let salt_buff = op.salt.as_ref().map(|salt| salt.as_slice());
74 | let buffer_size = key_attributes.asymmetric_decrypt_output_size(op.alg)?;
75 | let mut plaintext = vec![0u8; buffer_size];
76 |
77 | match asym_encryption::decrypt(id, op.alg, &op.ciphertext, salt_buff, &mut plaintext) {
78 | Ok(output_size) => {
79 | plaintext.resize(output_size, 0);
80 | Ok(psa_asymmetric_decrypt::Result {
81 | plaintext: plaintext.into(),
82 | })
83 | }
84 | Err(error) => {
85 | let error = ResponseStatus::from(error);
86 | format_error!("Decrypt status: ", error);
87 | Err(error)
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/providers/mbed_crypto/asym_sign.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use parsec_interface::operations::{psa_sign_hash, psa_verify_hash};
7 | use parsec_interface::requests::{ResponseStatus, Result};
8 | use psa_crypto::operations::asym_signature;
9 | use psa_crypto::types::key;
10 |
11 | impl Provider {
12 | pub(super) fn psa_sign_hash_internal(
13 | &self,
14 | application_identity: &ApplicationIdentity,
15 | op: psa_sign_hash::Operation,
16 | ) -> Result {
17 | let key_name = op.key_name.clone();
18 | let alg = op.alg;
19 | let key_identity = KeyIdentity::new(
20 | application_identity.clone(),
21 | self.provider_identity.clone(),
22 | key_name,
23 | );
24 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
25 |
26 | let _guard = self
27 | .key_handle_mutex
28 | .lock()
29 | .expect("Grabbing key handle mutex failed");
30 |
31 | let id = key::Id::from_persistent_key_id(key_id)?;
32 | let key_attributes = key::Attributes::from_key_id(id)?;
33 | let buffer_size = key_attributes.sign_output_size(alg)?;
34 | let mut signature = vec![0u8; buffer_size];
35 |
36 | op.validate(key_attributes)?;
37 |
38 | match asym_signature::sign_hash(id, alg, &(op.hash), &mut signature) {
39 | Ok(size) => {
40 | signature.resize(size, 0);
41 | Ok(psa_sign_hash::Result {
42 | signature: signature.into(),
43 | })
44 | }
45 | Err(error) => {
46 | let error = ResponseStatus::from(error);
47 | format_error!("Sign status: ", error);
48 | Err(error)
49 | }
50 | }
51 | }
52 |
53 | pub(super) fn psa_verify_hash_internal(
54 | &self,
55 | application_identity: &ApplicationIdentity,
56 | op: psa_verify_hash::Operation,
57 | ) -> Result {
58 | let key_name = op.key_name.clone();
59 | let alg = op.alg;
60 | let key_identity = KeyIdentity::new(
61 | application_identity.clone(),
62 | self.provider_identity.clone(),
63 | key_name,
64 | );
65 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
66 |
67 | let _guard = self
68 | .key_handle_mutex
69 | .lock()
70 | .expect("Grabbing key handle mutex failed");
71 |
72 | let id = key::Id::from_persistent_key_id(key_id)?;
73 | let key_attributes = key::Attributes::from_key_id(id)?;
74 | op.validate(key_attributes)?;
75 |
76 | let id = key::Id::from_persistent_key_id(key_id)?;
77 | match asym_signature::verify_hash(id, alg, &(op.hash), &(op.signature)) {
78 | Ok(()) => Ok(psa_verify_hash::Result {}),
79 | Err(error) => {
80 | let error = ResponseStatus::from(error);
81 | format_error!("Verify status: ", error);
82 | Err(error)
83 | }
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/providers/mbed_crypto/capability_discovery.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | use super::Provider;
5 | use crate::authenticators::ApplicationIdentity;
6 | use crate::providers::crypto_capability::CanDoCrypto;
7 | use log::{info, trace};
8 | use parsec_interface::operations::can_do_crypto;
9 | use parsec_interface::operations::psa_key_attributes::{Attributes, Type};
10 | use parsec_interface::requests::ResponseStatus::PsaErrorNotSupported;
11 | use parsec_interface::requests::Result;
12 |
13 | impl CanDoCrypto for Provider {
14 | fn can_do_crypto_internal(
15 | &self,
16 | _app_identity: &ApplicationIdentity,
17 | op: can_do_crypto::Operation,
18 | ) -> Result {
19 | trace!("can_do_crypto_internal");
20 |
21 | // Check if psa-crypto can convert the attributes into PSA structure
22 | // The conversion includes some validity checks.
23 | op.attributes.can_convert_into_psa().map_err(|_| {
24 | info!("Unsupported key attributes {:?}", op.attributes);
25 | PsaErrorNotSupported
26 | })?;
27 |
28 | Ok(can_do_crypto::Result)
29 | }
30 |
31 | fn use_check_internal(&self, attributes: Attributes) -> Result {
32 | trace!("use_check_internal");
33 |
34 | let _ = Provider::check_key_size(attributes, false).map_err(|_| {
35 | info!("Unsupported key size {}", attributes.bits);
36 | PsaErrorNotSupported
37 | })?;
38 |
39 | Ok(can_do_crypto::Result)
40 | }
41 |
42 | fn generate_check_internal(&self, attributes: Attributes) -> Result {
43 | trace!("generate_check_internal");
44 |
45 | let _ = Provider::check_key_size(attributes, false).map_err(|_| {
46 | info!("Unsupported key size {}", attributes.bits);
47 | PsaErrorNotSupported
48 | })?;
49 |
50 | match attributes.key_type {
51 | Type::RsaKeyPair
52 | | Type::EccKeyPair { .. }
53 | | Type::DhKeyPair { .. }
54 | | Type::RawData
55 | | Type::Aes
56 | | Type::Camellia
57 | | Type::Chacha20 => Ok(can_do_crypto::Result),
58 | _ => {
59 | info!("Unsupported key type {:?}", attributes.key_type);
60 | Err(PsaErrorNotSupported)
61 | }
62 | }
63 | }
64 |
65 | fn import_check_internal(&self, attributes: Attributes) -> Result {
66 | trace!("import_check_internal");
67 |
68 | let _ = Provider::check_key_size(attributes, true).map_err(|_| {
69 | info!("Unsupported key size {}", attributes.bits);
70 | PsaErrorNotSupported
71 | })?;
72 |
73 | // We can import public keys and all the types we can generate.
74 | match attributes.key_type {
75 | Type::RsaPublicKey | Type::EccPublicKey { .. } | Type::DhPublicKey { .. } => {
76 | Ok(can_do_crypto::Result)
77 | }
78 | Type::RsaKeyPair
79 | | Type::EccKeyPair { .. }
80 | | Type::DhKeyPair { .. }
81 | | Type::RawData
82 | | Type::Aes
83 | | Type::Camellia
84 | | Type::Chacha20 => Ok(can_do_crypto::Result),
85 | _ => {
86 | info!("Unsupported key type {:?}", attributes.key_type);
87 | Err(PsaErrorNotSupported)
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/providers/mbed_crypto/generate_random.rs:
--------------------------------------------------------------------------------
1 | use super::Provider;
2 | use parsec_interface::operations::psa_generate_random;
3 | use parsec_interface::requests::{ResponseStatus, Result};
4 | use psa_crypto::operations::other::generate_random;
5 |
6 | impl Provider {
7 | pub(super) fn psa_generate_random_internal(
8 | &self,
9 | op: psa_generate_random::Operation,
10 | ) -> Result {
11 | let buffer_size = op.size;
12 | if buffer_size > crate::utils::GlobalConfig::buffer_size_limit() {
13 | let error = ResponseStatus::ResponseTooLarge;
14 | format_error!("Generate random status", error);
15 | return Err(error);
16 | }
17 |
18 | let mut buffer = vec![0u8; buffer_size];
19 | match generate_random(&mut buffer) {
20 | Ok(_) => Ok(psa_generate_random::Result {
21 | random_bytes: buffer.into(),
22 | }),
23 | Err(error) => {
24 | let error = ResponseStatus::from(error);
25 | format_error!("Generate random status", error);
26 | Err(error)
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/providers/mbed_crypto/hash.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use parsec_interface::operations::{psa_hash_compare, psa_hash_compute};
5 | use parsec_interface::requests::{ResponseStatus, Result};
6 | use psa_crypto::operations::hash;
7 |
8 | impl Provider {
9 | pub(super) fn psa_hash_compute_internal(
10 | &self,
11 | op: psa_hash_compute::Operation,
12 | ) -> Result {
13 | let mut hash = vec![0u8; op.alg.hash_length()];
14 |
15 | match hash::hash_compute(op.alg, &op.input, &mut hash) {
16 | Ok(hash_size) => {
17 | hash.resize(hash_size, 0);
18 | Ok(psa_hash_compute::Result { hash: hash.into() })
19 | }
20 | Err(error) => {
21 | let error = ResponseStatus::from(error);
22 | format_error!("Has compute status: ", error);
23 | Err(error)
24 | }
25 | }
26 | }
27 |
28 | pub(super) fn psa_hash_compare_internal(
29 | &self,
30 | op: psa_hash_compare::Operation,
31 | ) -> Result {
32 | match hash::hash_compare(op.alg, &op.input, &op.hash) {
33 | Ok(()) => Ok(psa_hash_compare::Result),
34 | Err(error) => {
35 | let error = ResponseStatus::from(error);
36 | format_error!("Hash compare status: ", error);
37 | Err(error)
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/providers/mbed_crypto/key_agreement.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use parsec_interface::operations::psa_raw_key_agreement;
7 | use parsec_interface::requests::{ResponseStatus, Result};
8 | use parsec_interface::secrecy::Secret;
9 | use psa_crypto::operations::key_agreement;
10 | use psa_crypto::types::key;
11 |
12 | impl Provider {
13 | pub(super) fn psa_raw_key_agreement(
14 | &self,
15 | application_identity: &ApplicationIdentity,
16 | op: psa_raw_key_agreement::Operation,
17 | ) -> Result {
18 | let key_name = op.private_key_name.clone();
19 |
20 | let key_identity = KeyIdentity::new(
21 | application_identity.clone(),
22 | self.provider_identity.clone(),
23 | key_name,
24 | );
25 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
26 | let _guard = self
27 | .key_handle_mutex
28 | .lock()
29 | .expect("Grabbing key handle mutex failed");
30 | let id = key::Id::from_persistent_key_id(key_id)?;
31 | let key_attributes = key::Attributes::from_key_id(id)?;
32 |
33 | op.validate(key_attributes)?;
34 | let buffer_size = key_attributes.raw_key_agreement_output_size(op.alg)?;
35 | let mut shared_secret = vec![0u8; buffer_size];
36 |
37 | match key_agreement::raw_key_agreement(op.alg, id, &op.peer_key, &mut shared_secret) {
38 | Ok(output_size) => {
39 | shared_secret.resize(output_size, 0);
40 | Ok(psa_raw_key_agreement::Result {
41 | shared_secret: Secret::new(shared_secret),
42 | })
43 | }
44 | Err(error) => {
45 | let error = ResponseStatus::from(error);
46 | format_error!("Raw key agreement status: ", error);
47 | Err(error)
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/providers/pkcs11/generate_random.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::utils::to_response_status;
4 | use super::Provider;
5 | use log::error;
6 | use parsec_interface::operations::psa_generate_random;
7 | use parsec_interface::requests::{ResponseStatus, Result};
8 | use std::convert::TryFrom;
9 |
10 | impl Provider {
11 | pub(super) fn psa_generate_random_internal(
12 | &self,
13 | op: psa_generate_random::Operation,
14 | ) -> Result {
15 | let length = u32::try_from(op.size).or_else(|_| {
16 | let error = ResponseStatus::PsaErrorGenericError;
17 | error!("Requested size is too large");
18 | Err(error)
19 | })?;
20 |
21 | let session = self.new_session()?;
22 |
23 | Ok(psa_generate_random::Result {
24 | random_bytes: session
25 | .generate_random_vec(length)
26 | .map_err(to_response_status)?
27 | .into(),
28 | })
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/providers/pkcs11/key_metadata.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 |
5 | impl Provider {
6 | pub(super) fn create_key_id(&self) -> u32 {
7 | let mut local_ids_handle = self.local_ids.write().expect("Local ID lock poisoned");
8 | let mut key_id = rand::random::();
9 | while local_ids_handle.contains(&key_id) {
10 | key_id = rand::random::();
11 | }
12 | let _ = local_ids_handle.insert(key_id);
13 | key_id
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/providers/tpm/asym_sign.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::{utils, Provider};
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use log::error;
7 | use parsec_interface::operations::psa_algorithm::*;
8 | use parsec_interface::operations::{psa_sign_hash, psa_verify_hash};
9 | use parsec_interface::requests::{ResponseStatus, Result};
10 | use std::convert::TryFrom;
11 | use tss_esapi::structures::{Auth, Digest};
12 |
13 | impl Provider {
14 | pub(super) fn psa_sign_hash_internal(
15 | &self,
16 | application_identity: &ApplicationIdentity,
17 | op: psa_sign_hash::Operation,
18 | ) -> Result {
19 | let key_identity = KeyIdentity::new(
20 | application_identity.clone(),
21 | self.provider_identity.clone(),
22 | op.key_name.clone(),
23 | );
24 |
25 | let password_context = self.get_key_ctx(&key_identity)?;
26 | let key_attributes = self.key_info_store.get_key_attributes(&key_identity)?;
27 |
28 | let mut esapi_context = self
29 | .esapi_context
30 | .lock()
31 | .expect("ESAPI Context lock poisoned");
32 |
33 | match op.alg {
34 | AsymmetricSignature::RsaPkcs1v15Sign { .. } => (),
35 | AsymmetricSignature::Ecdsa { .. } => (),
36 | _ => {
37 | if crate::utils::GlobalConfig::log_error_details() {
38 | error!(
39 | "Requested algorithm is not supported by the TPM provider: {:?}",
40 | op.alg
41 | );
42 | } else {
43 | error!("Requested algorithm is not supported by the TPM provider");
44 | }
45 | return Err(ResponseStatus::PsaErrorNotSupported);
46 | }
47 | }
48 |
49 | op.validate(key_attributes)?;
50 |
51 | let signature = esapi_context
52 | .sign(
53 | password_context.key_material().clone(),
54 | utils::parsec_to_tpm_params(key_attributes)?,
55 | Some(
56 | Auth::try_from(password_context.auth_value().to_vec())
57 | .map_err(utils::to_response_status)?,
58 | ),
59 | Digest::try_from((*op.hash).clone()).map_err(utils::to_response_status)?,
60 | )
61 | .map_err(|e| {
62 | if crate::utils::GlobalConfig::log_error_details() {
63 | error!("Error signing: {}.", e);
64 | }
65 | utils::to_response_status(e)
66 | })?;
67 |
68 | Ok(psa_sign_hash::Result {
69 | signature: utils::signature_data_to_bytes(signature, key_attributes)?.into(),
70 | })
71 | }
72 |
73 | pub(super) fn psa_verify_hash_internal(
74 | &self,
75 | application_identity: &ApplicationIdentity,
76 | op: psa_verify_hash::Operation,
77 | ) -> Result {
78 | let key_identity = KeyIdentity::new(
79 | application_identity.clone(),
80 | self.provider_identity.clone(),
81 | op.key_name.clone(),
82 | );
83 |
84 | let password_context = self.get_key_ctx(&key_identity)?;
85 | let key_attributes = self.key_info_store.get_key_attributes(&key_identity)?;
86 |
87 | let mut esapi_context = self
88 | .esapi_context
89 | .lock()
90 | .expect("ESAPI Context lock poisoned");
91 |
92 | match op.alg {
93 | AsymmetricSignature::RsaPkcs1v15Sign { .. } => (),
94 | AsymmetricSignature::Ecdsa { .. } => (),
95 | _ => {
96 | if crate::utils::GlobalConfig::log_error_details() {
97 | error!(
98 | "Requested algorithm is not supported by the TPM provider: {:?}",
99 | op.alg
100 | );
101 | } else {
102 | error!("Requested algorithm is not supported by the TPM provider");
103 | }
104 | return Err(ResponseStatus::PsaErrorNotSupported);
105 | }
106 | }
107 |
108 | op.validate(key_attributes)?;
109 |
110 | let signature = utils::parsec_to_tpm_signature(op.signature, key_attributes, op.alg)?;
111 |
112 | let _ = esapi_context
113 | .verify_signature(
114 | password_context.key_material().clone(),
115 | utils::parsec_to_tpm_params(key_attributes)?,
116 | Digest::try_from((*op.hash).clone()).map_err(utils::to_response_status)?,
117 | signature,
118 | )
119 | .map_err(utils::to_response_status)?;
120 |
121 | Ok(psa_verify_hash::Result {})
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/providers/tpm/capability_discovery.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | use super::{utils, Provider};
5 | use crate::authenticators::ApplicationIdentity;
6 | use crate::providers::crypto_capability::CanDoCrypto;
7 | use log::{info, trace};
8 | use parsec_interface::operations::can_do_crypto;
9 | use parsec_interface::operations::psa_key_attributes::{Attributes, Type};
10 | use parsec_interface::requests::ResponseStatus::PsaErrorNotSupported;
11 | use parsec_interface::requests::Result;
12 |
13 | impl CanDoCrypto for Provider {
14 | fn can_do_crypto_internal(
15 | &self,
16 | _application_identity: &ApplicationIdentity,
17 | op: can_do_crypto::Operation,
18 | ) -> Result {
19 | trace!("can_do_crypto_internal");
20 |
21 | // Check attributes compatibility with the provider
22 | match op.attributes.key_type {
23 | Type::RsaKeyPair | Type::RsaPublicKey => {
24 | let _ =
25 | utils::rsa_key_bits(op.attributes.bits).map_err(|_| PsaErrorNotSupported)?;
26 | Ok(can_do_crypto::Result)
27 | }
28 | Type::EccKeyPair { .. } | Type::EccPublicKey { .. } => {
29 | let _ = utils::convert_curve_to_tpm(op.attributes)?;
30 | Ok(can_do_crypto::Result)
31 | }
32 | _ => {
33 | info!("Unsupported key type {:?}", op.attributes.key_type);
34 | Err(PsaErrorNotSupported)
35 | }
36 | }
37 | }
38 |
39 | fn use_check_internal(&self, attributes: Attributes) -> Result {
40 | trace!("use_check_internal");
41 |
42 | let _ = utils::parsec_to_tpm_params(attributes).map_err(|_| PsaErrorNotSupported)?;
43 |
44 | // TO-DO we also need to check capabilities of used TMP module.
45 | // TPM_GetCapability support in the tss-esapi crate is required.
46 | Ok(can_do_crypto::Result)
47 | }
48 |
49 | fn generate_check_internal(&self, attributes: Attributes) -> Result {
50 | trace!("generate_check_internal");
51 | match attributes.key_type {
52 | Type::RsaKeyPair | Type::EccKeyPair { .. } => Ok(can_do_crypto::Result),
53 | _ => {
54 | info!("Unsupported key type {:?}", attributes.key_type);
55 | Err(PsaErrorNotSupported)
56 | }
57 | }
58 | }
59 |
60 | fn import_check_internal(&self, attributes: Attributes) -> Result {
61 | trace!("import_check_internal");
62 | match attributes.key_type {
63 | Type::RsaPublicKey | Type::EccPublicKey { .. } => Ok(can_do_crypto::Result),
64 | _ => {
65 | info!("Unsupported key type {:?}", attributes.key_type);
66 | Err(PsaErrorNotSupported)
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/providers/tpm/generate_random.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::utils;
4 | use super::Provider;
5 | use parsec_interface::operations::psa_generate_random;
6 | use parsec_interface::requests::Result;
7 |
8 | impl Provider {
9 | pub(super) fn psa_generate_random_internal(
10 | &self,
11 | op: psa_generate_random::Operation,
12 | ) -> Result {
13 | let size = op.size;
14 |
15 | let mut esapi_context = self
16 | .esapi_context
17 | .lock()
18 | .expect("ESAPI Context lock poisoned");
19 |
20 | let random_bytes = esapi_context
21 | .as_mut()
22 | .execute_without_session(|esapi_context| esapi_context.get_random(size))
23 | .map_err(|e| {
24 | format_error!("Failed to get random bytes", e);
25 | utils::to_response_status(e)
26 | })?;
27 | Ok(psa_generate_random::Result {
28 | random_bytes: random_bytes.value().to_vec().into(),
29 | })
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/asym_encryption.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use log::error;
7 | use parsec_interface::operations::{psa_asymmetric_decrypt, psa_asymmetric_encrypt};
8 | use parsec_interface::requests::Result;
9 |
10 | impl Provider {
11 | pub(super) fn psa_asymmetric_encrypt_internal(
12 | &self,
13 | application_identity: &ApplicationIdentity,
14 | op: psa_asymmetric_encrypt::Operation,
15 | ) -> Result {
16 | let key_identity = KeyIdentity::new(
17 | application_identity.clone(),
18 | self.provider_identity.clone(),
19 | op.key_name.clone(),
20 | );
21 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
22 | let salt_buff = match &op.salt {
23 | Some(salt) => salt.to_vec(),
24 | None => Vec::new(),
25 | };
26 |
27 | match self
28 | .context
29 | .asym_encrypt(key_id, op.alg, op.plaintext.to_vec(), salt_buff)
30 | {
31 | Ok(ciphertext) => Ok(psa_asymmetric_encrypt::Result {
32 | ciphertext: ciphertext.into(),
33 | }),
34 | Err(error) => {
35 | error!("Encrypt failed with status: {}", error);
36 | Err(error)
37 | }
38 | }
39 | }
40 |
41 | pub(super) fn psa_asymmetric_decrypt_internal(
42 | &self,
43 | application_identity: &ApplicationIdentity,
44 | op: psa_asymmetric_decrypt::Operation,
45 | ) -> Result {
46 | let key_identity = KeyIdentity::new(
47 | application_identity.clone(),
48 | self.provider_identity.clone(),
49 | op.key_name.clone(),
50 | );
51 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
52 | let salt_buff = match &op.salt {
53 | Some(salt) => salt.to_vec(),
54 | None => Vec::new(),
55 | };
56 |
57 | match self
58 | .context
59 | .asym_decrypt(key_id, op.alg, op.ciphertext.to_vec(), salt_buff)
60 | {
61 | Ok(plaintext) => Ok(psa_asymmetric_decrypt::Result {
62 | plaintext: plaintext.into(),
63 | }),
64 | Err(error) => {
65 | error!("Decrypt failed with status: {}", error);
66 | Err(error)
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/asym_sign.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use crate::authenticators::ApplicationIdentity;
5 | use crate::key_info_managers::KeyIdentity;
6 | use parsec_interface::operations::{psa_sign_hash, psa_verify_hash};
7 | use parsec_interface::requests::Result;
8 |
9 | impl Provider {
10 | pub(super) fn psa_sign_hash_internal(
11 | &self,
12 | application_identity: &ApplicationIdentity,
13 | op: psa_sign_hash::Operation,
14 | ) -> Result {
15 | let key_identity = KeyIdentity::new(
16 | application_identity.clone(),
17 | self.provider_identity.clone(),
18 | op.key_name.clone(),
19 | );
20 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
21 | let key_attributes = self.key_info_store.get_key_attributes(&key_identity)?;
22 | op.validate(key_attributes)?;
23 |
24 | Ok(psa_sign_hash::Result {
25 | signature: self
26 | .context
27 | .sign_hash(key_id, op.hash.to_vec(), op.alg)?
28 | .into(),
29 | })
30 | }
31 |
32 | pub(super) fn psa_verify_hash_internal(
33 | &self,
34 | application_identity: &ApplicationIdentity,
35 | op: psa_verify_hash::Operation,
36 | ) -> Result {
37 | let key_identity = KeyIdentity::new(
38 | application_identity.clone(),
39 | self.provider_identity.clone(),
40 | op.key_name.clone(),
41 | );
42 | let key_id = self.key_info_store.get_key_id(&key_identity)?;
43 | let key_attributes = self.key_info_store.get_key_attributes(&key_identity)?;
44 | op.validate(key_attributes)?;
45 |
46 | self.context
47 | .verify_hash(key_id, op.hash.to_vec(), op.signature.to_vec(), op.alg)?;
48 |
49 | Ok(psa_verify_hash::Result {})
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/capability_discovery.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | use super::Provider;
5 | use crate::authenticators::ApplicationIdentity;
6 | use crate::providers::crypto_capability::CanDoCrypto;
7 | use log::{info, trace};
8 | use parsec_interface::operations::can_do_crypto;
9 | use parsec_interface::operations::psa_key_attributes::{Attributes, Type};
10 | use parsec_interface::requests::ResponseStatus::PsaErrorNotSupported;
11 | use parsec_interface::requests::Result;
12 |
13 | impl CanDoCrypto for Provider {
14 | fn can_do_crypto_internal(
15 | &self,
16 | _app_identity: &ApplicationIdentity,
17 | op: can_do_crypto::Operation,
18 | ) -> Result {
19 | trace!("can_do_crypto_internal");
20 |
21 | // Check if psa-crypto can convert the attributes into PSA structure
22 | // The conversion includes some validity checks.
23 | op.attributes.can_convert_into_psa().map_err(|_| {
24 | info!("Unsupported key attributes {:?}", op.attributes);
25 | PsaErrorNotSupported
26 | })?;
27 |
28 | Ok(can_do_crypto::Result)
29 | }
30 |
31 | fn use_check_internal(&self, attributes: Attributes) -> Result {
32 | trace!("use_check_internal");
33 |
34 | let _ = Provider::check_key_size(attributes, false).map_err(|_| {
35 | info!("Unsupported key size {}", attributes.bits);
36 | PsaErrorNotSupported
37 | })?;
38 |
39 | Ok(can_do_crypto::Result)
40 | }
41 |
42 | fn generate_check_internal(&self, attributes: Attributes) -> Result {
43 | trace!("generate_check_internal");
44 |
45 | let _ = Provider::check_key_size(attributes, false).map_err(|_| {
46 | info!("Unsupported key size {}", attributes.bits);
47 | PsaErrorNotSupported
48 | })?;
49 |
50 | match attributes.key_type {
51 | Type::RsaKeyPair
52 | | Type::EccKeyPair { .. }
53 | | Type::DhKeyPair { .. }
54 | | Type::RawData
55 | | Type::Aes
56 | | Type::Camellia
57 | | Type::Chacha20 => Ok(can_do_crypto::Result),
58 | _ => {
59 | info!("Unsupported key type {:?}", attributes.key_type);
60 | Err(PsaErrorNotSupported)
61 | }
62 | }
63 | }
64 |
65 | fn import_check_internal(&self, attributes: Attributes) -> Result {
66 | trace!("import_check_internal");
67 |
68 | let _ = Provider::check_key_size(attributes, true).map_err(|_| {
69 | info!("Unsupported key size {}", attributes.bits);
70 | PsaErrorNotSupported
71 | })?;
72 |
73 | // We can import public keys and all the types we can generate.
74 | match attributes.key_type {
75 | Type::RsaPublicKey | Type::EccPublicKey { .. } | Type::DhPublicKey { .. } => {
76 | Ok(can_do_crypto::Result)
77 | }
78 | Type::RsaKeyPair
79 | | Type::EccKeyPair { .. }
80 | | Type::DhKeyPair { .. }
81 | | Type::RawData
82 | | Type::Aes
83 | | Type::Camellia
84 | | Type::Chacha20 => Ok(can_do_crypto::Result),
85 | _ => {
86 | info!("Unsupported key type {:?}", attributes.key_type);
87 | Err(PsaErrorNotSupported)
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/context/asym_encryption.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::ts_protobuf::{
4 | AsymmetricDecryptIn, AsymmetricDecryptOut, AsymmetricEncryptIn, AsymmetricEncryptOut,
5 | };
6 | use super::Context;
7 | use parsec_interface::operations::psa_algorithm::AsymmetricEncryption;
8 | use parsec_interface::requests::ResponseStatus;
9 |
10 | impl Context {
11 | pub fn asym_encrypt(
12 | &self,
13 | key_id: u32,
14 | alg: AsymmetricEncryption,
15 | plaintext: Vec,
16 | salt: Vec,
17 | ) -> Result, ResponseStatus> {
18 | let alg = alg.into();
19 | let req = AsymmetricEncryptIn {
20 | id: key_id,
21 | alg,
22 | plaintext,
23 | salt,
24 | };
25 | let AsymmetricEncryptOut { ciphertext } = self.send_request(&req)?;
26 |
27 | Ok(ciphertext)
28 | }
29 |
30 | pub fn asym_decrypt(
31 | &self,
32 | key_id: u32,
33 | alg: AsymmetricEncryption,
34 | ciphertext: Vec,
35 | salt: Vec,
36 | ) -> Result, ResponseStatus> {
37 | let alg = alg.into();
38 | let req = AsymmetricDecryptIn {
39 | id: key_id,
40 | alg,
41 | ciphertext,
42 | salt,
43 | };
44 | let AsymmetricDecryptOut { plaintext } = self.send_request(&req)?;
45 |
46 | Ok(plaintext)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/context/asym_sign.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::error::Error;
4 | use super::ts_protobuf::{SignHashIn, SignHashOut, VerifyHashIn};
5 | use super::Context;
6 | use log::info;
7 | use psa_crypto::types::algorithm::AsymmetricSignature;
8 |
9 | impl Context {
10 | /// Sign a hash with an asymmetric key given its ID and the signing algorithm.
11 | pub fn sign_hash(
12 | &self,
13 | key_id: u32,
14 | hash: Vec,
15 | algorithm: AsymmetricSignature,
16 | ) -> Result, Error> {
17 | info!("Handling SignHash request");
18 | let proto_req = SignHashIn {
19 | id: key_id,
20 | hash,
21 | alg: algorithm.into(),
22 | };
23 | let SignHashOut { signature } = self.send_request(&proto_req)?;
24 |
25 | Ok(signature)
26 | }
27 |
28 | /// Verify a signature on a hash with an asymmetric key given its ID and the signing algorithm.
29 | pub fn verify_hash(
30 | &self,
31 | key_id: u32,
32 | hash: Vec,
33 | signature: Vec,
34 | algorithm: AsymmetricSignature,
35 | ) -> Result<(), Error> {
36 | info!("Handling VerifyHash request");
37 | let proto_req = VerifyHashIn {
38 | id: key_id,
39 | hash,
40 | signature,
41 | alg: algorithm.into(),
42 | };
43 | self.send_request(&proto_req)?;
44 |
45 | Ok(())
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/context/generate_random.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::error::Error;
4 | use super::ts_protobuf::{GenerateRandomIn, GenerateRandomOut};
5 | use super::Context;
6 | use log::info;
7 | use std::convert::TryInto;
8 |
9 | impl Context {
10 | pub fn generate_random(&self, size: usize) -> Result, Error> {
11 | info!("Handling GenerateRandom request");
12 | let open_req: GenerateRandomIn = GenerateRandomIn {
13 | size: size.try_into()?,
14 | };
15 | let result: GenerateRandomOut = self.send_request(&open_req)?;
16 | Ok(result.random_bytes)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/context/key_management.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::error::Error;
4 | use super::ts_protobuf::{
5 | DestroyKeyIn, DestroyKeyOut, ExportKeyIn, ExportPublicKeyIn, GenerateKeyIn, ImportKeyIn,
6 | KeyAttributes, KeyLifetime, KeyPolicy,
7 | };
8 | use super::Context;
9 | use log::info;
10 | use psa_crypto::types::key::Attributes;
11 | use std::convert::{TryFrom, TryInto};
12 | use zeroize::Zeroize;
13 |
14 | impl Context {
15 | /// Generate a key given its attributes and ID
16 | ///
17 | /// Lifetime flexibility is not supported: the `lifetime` parameter in the key
18 | /// attributes is essentially ignored and replaced with `KeyLifetime::Persistent`.
19 | pub fn generate_key(&self, key_attrs: Attributes, id: u32) -> Result<(), Error> {
20 | info!("Handling GenerateKey request");
21 | let generate_req = GenerateKeyIn {
22 | attributes: Some(KeyAttributes {
23 | r#type: u16::try_from(key_attrs.key_type)? as u32,
24 | key_bits: key_attrs.bits.try_into()?,
25 | lifetime: KeyLifetime::Persistent as u32,
26 | id,
27 | policy: Some(KeyPolicy {
28 | usage: key_attrs.policy.usage_flags.into(),
29 | alg: key_attrs.policy.permitted_algorithms.try_into()?,
30 | }),
31 | }),
32 | };
33 | self.send_request(&generate_req)?;
34 |
35 | Ok(())
36 | }
37 |
38 | /// Import a key given its attributes, ID, and key data.
39 | ///
40 | /// Lifetime flexibility is not supported: the `lifetime` parameter in the key
41 | /// attributes is essentially ignored and replaced with `KeyLifetime::Persistent`.
42 | ///
43 | /// Key data must be in the format described by the PSA Crypto format.
44 | pub fn import_key(&self, key_attrs: Attributes, id: u32, key_data: &[u8]) -> Result<(), Error> {
45 | info!("Handling ImportKey request");
46 | let mut data = key_data.to_vec();
47 | let import_req = ImportKeyIn {
48 | attributes: Some(KeyAttributes {
49 | r#type: u16::try_from(key_attrs.key_type).map_err(|e| {
50 | data.zeroize();
51 | e
52 | })? as u32,
53 | key_bits: key_attrs.bits.try_into().map_err(|e| {
54 | data.zeroize();
55 | e
56 | })?,
57 | lifetime: KeyLifetime::Persistent as u32,
58 | id,
59 | policy: Some(KeyPolicy {
60 | usage: key_attrs.policy.usage_flags.into(),
61 | alg: key_attrs
62 | .policy
63 | .permitted_algorithms
64 | .try_into()
65 | .map_err(|e| {
66 | data.zeroize();
67 | e
68 | })?,
69 | }),
70 | }),
71 | data,
72 | };
73 | self.send_request(&import_req)?;
74 |
75 | Ok(())
76 | }
77 |
78 | /// Export the public part of a key given its ID.
79 | ///
80 | /// The public key data is returned in the format specified by the PSA Crypto
81 | /// format.
82 | pub fn export_public_key(&self, id: u32) -> Result, Error> {
83 | info!("Handling ExportPublicKey request");
84 | let req = ExportPublicKeyIn { id };
85 | self.send_request(&req)
86 | }
87 |
88 | /// Export the key given its ID.
89 | pub fn export_key(&self, id: u32) -> Result, Error> {
90 | info!("Handling ExportKey request");
91 | let req = ExportKeyIn { id };
92 | self.send_request(&req)
93 | }
94 |
95 | /// Destroy a key given its ID.
96 | pub fn destroy_key(&self, key_id: u32) -> Result<(), Error> {
97 | info!("Handling DestroyKey request");
98 |
99 | let destroy_req = DestroyKeyIn { id: key_id };
100 | let _proto_resp: DestroyKeyOut = self.send_request(&destroy_req)?;
101 | Ok(())
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/context/ts_protobuf.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | #![allow(
4 | non_snake_case,
5 | non_camel_case_types,
6 | non_upper_case_globals,
7 | clippy::unseparated_literal_suffix,
8 | // There is an issue where long double become u128 in extern blocks. Check this issue:
9 | // https://github.com/rust-lang/rust-bindgen/issues/1549
10 | improper_ctypes,
11 | missing_debug_implementations,
12 | trivial_casts,
13 | clippy::all,
14 | unused,
15 | unused_qualifications
16 | )]
17 | use zeroize::Zeroize;
18 |
19 | include!(concat!(env!("OUT_DIR"), "/ts_crypto.rs"));
20 |
21 | /// Trait for associating an Opcode with each operation type
22 | /// and obtaining it in a generic way.
23 | pub trait GetOpcode {
24 | fn opcode(&self) -> Opcode;
25 | }
26 |
27 | macro_rules! opcode_impl {
28 | ($type:ty, $opcode:ident) => {
29 | impl GetOpcode for $type {
30 | fn opcode(&self) -> Opcode {
31 | Opcode::$opcode
32 | }
33 | }
34 | };
35 |
36 | ($type_in:ty, $type_out:ty, $opcode:ident) => {
37 | impl GetOpcode for $type_in {
38 | fn opcode(&self) -> Opcode {
39 | Opcode::$opcode
40 | }
41 | }
42 |
43 | impl GetOpcode for $type_out {
44 | fn opcode(&self) -> Opcode {
45 | Opcode::$opcode
46 | }
47 | }
48 | };
49 | }
50 |
51 | opcode_impl!(GenerateKeyIn, GenerateKeyOut, GenerateKey);
52 | opcode_impl!(DestroyKeyIn, DestroyKeyOut, DestroyKey);
53 | opcode_impl!(SignHashIn, SignHashOut, SignHash);
54 | opcode_impl!(VerifyHashIn, VerifyHashOut, VerifyHash);
55 | opcode_impl!(ImportKeyIn, ImportKeyOut, ImportKey);
56 | opcode_impl!(ExportPublicKeyIn, ExportPublicKeyOut, ExportPublicKey);
57 | opcode_impl!(ExportKeyIn, ExportKeyOut, ExportKey);
58 | opcode_impl!(GenerateRandomIn, GenerateRandomOut, GenerateRandom);
59 | opcode_impl!(AsymmetricDecryptIn, AsymmetricDecryptOut, AsymmetricDecrypt);
60 | opcode_impl!(AsymmetricEncryptIn, AsymmetricEncryptOut, AsymmetricEncrypt);
61 |
62 | impl Drop for ImportKeyIn {
63 | fn drop(&mut self) {
64 | self.data.zeroize();
65 | }
66 | }
67 |
68 | impl Drop for ExportKeyOut {
69 | fn drop(&mut self) {
70 | self.data.zeroize();
71 | }
72 | }
73 |
74 | impl Drop for SignHashIn {
75 | fn drop(&mut self) {
76 | self.hash.zeroize();
77 | }
78 | }
79 |
80 | impl Drop for VerifyHashIn {
81 | fn drop(&mut self) {
82 | self.hash.zeroize();
83 | self.signature.zeroize();
84 | }
85 | }
86 |
87 | impl Drop for AsymmetricEncryptIn {
88 | fn drop(&mut self) {
89 | self.plaintext.zeroize();
90 | self.salt.zeroize();
91 | }
92 | }
93 |
94 | impl Drop for AsymmetricDecryptIn {
95 | fn drop(&mut self) {
96 | self.ciphertext.zeroize();
97 | self.salt.zeroize();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/error.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::context::error::{Error, RpcCallerError, WrapperError};
4 | use parsec_interface::requests::ResponseStatus;
5 |
6 | impl From for ResponseStatus {
7 | fn from(error: RpcCallerError) -> Self {
8 | match error {
9 | RpcCallerError::EndpointDoesNotExist
10 | | RpcCallerError::InvalidOpcode
11 | | RpcCallerError::SerializationNotSupported
12 | | RpcCallerError::ResourceFailure
13 | | RpcCallerError::NotReady
14 | | RpcCallerError::InvalidTransaction
15 | | RpcCallerError::Internal
16 | | RpcCallerError::InvalidResponseBody
17 | | RpcCallerError::InvalidParameter => ResponseStatus::PsaErrorCommunicationFailure,
18 | RpcCallerError::InvalidRequestBody => ResponseStatus::PsaErrorInvalidArgument,
19 | }
20 | }
21 | }
22 |
23 | impl From for ResponseStatus {
24 | fn from(error: WrapperError) -> Self {
25 | match error {
26 | WrapperError::CallBufferNull
27 | | WrapperError::CallHandleNull
28 | | WrapperError::FailedPbConversion
29 | | WrapperError::InvalidParam
30 | | WrapperError::InvalidOpStatus => ResponseStatus::PsaErrorCommunicationFailure,
31 | }
32 | }
33 | }
34 |
35 | impl From for ResponseStatus {
36 | fn from(error: Error) -> Self {
37 | match error {
38 | Error::PsaCrypto(e) => e.into(),
39 | Error::RpcCaller(e) => e.into(),
40 | Error::Wrapper(e) => e.into(),
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/providers/trusted_service/generate_random.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use super::Provider;
4 | use parsec_interface::operations::psa_generate_random;
5 | use parsec_interface::requests::Result;
6 |
7 | impl Provider {
8 | pub(super) fn psa_generate_random_internal(
9 | &self,
10 | op: psa_generate_random::Operation,
11 | ) -> Result {
12 | let size = op.size;
13 |
14 | match self.context.generate_random(size) {
15 | Ok(random_bytes) => Ok(psa_generate_random::Result {
16 | random_bytes: random_bytes.into(),
17 | }),
18 | Err(error) => {
19 | format_error!("Generate random status: ", error);
20 | Err(error.into())
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/utils/cli.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! Command Line Interface configuration
4 |
5 | // WARNING: This file should be only updated in a non-breaking way. CLI flags should not be
6 | // removed, new flags should be tested.
7 | // See https://github.com/parallaxsecond/parsec/issues/392 for details.
8 | #![allow(unused_qualifications)]
9 |
10 | use clap::Parser;
11 |
12 | /// Parsec is the Platform AbstRaction for SECurity, a new open-source initiative to provide a
13 | /// common API to secure services in a platform-agnostic way.
14 | ///
15 | /// Parsec documentation is available at:
16 | /// https://parallaxsecond.github.io/parsec-book/index.html
17 | ///
18 | /// Most of Parsec configuration comes from its configuration file.
19 | /// Please check the documentation to find more about configuration:
20 | /// https://parallaxsecond.github.io/parsec-book/user_guides/configuration.html
21 | #[derive(Parser, Debug)]
22 | pub struct Opts {
23 | /// Sets the configuration file path
24 | #[structopt(short, long, default_value = "config.toml")]
25 | pub config: String,
26 | }
27 |
--------------------------------------------------------------------------------
/src/utils/global_config.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | use crate::utils::service_builder::DEFAULT_BUFFER_SIZE_LIMIT;
4 | use std::sync::atomic::Ordering;
5 | use std::sync::atomic::{AtomicBool, AtomicUsize};
6 |
7 | /// Configuration values that affect most or all the
8 | /// components of the service.
9 | #[derive(Default, Debug)]
10 | pub struct GlobalConfig {
11 | log_error_details: AtomicBool,
12 | buffer_size_limit: AtomicUsize,
13 | allow_deprecated: AtomicBool,
14 | }
15 |
16 | impl GlobalConfig {
17 | const fn new() -> Self {
18 | GlobalConfig {
19 | log_error_details: AtomicBool::new(false),
20 | buffer_size_limit: AtomicUsize::new(DEFAULT_BUFFER_SIZE_LIMIT), // 1 MB
21 | allow_deprecated: AtomicBool::new(false),
22 | }
23 | }
24 |
25 | /// Determine whether error logs should include detailed
26 | /// information about the error
27 | pub fn log_error_details() -> bool {
28 | GLOBAL_CONFIG.log_error_details.load(Ordering::Relaxed)
29 | }
30 |
31 | /// Fetch the size limit for buffers within responses (in bytes).
32 | /// information about the error
33 | pub fn buffer_size_limit() -> usize {
34 | GLOBAL_CONFIG.buffer_size_limit.load(Ordering::Relaxed)
35 | }
36 |
37 | /// Determine whether deprecated algorithms and key types are allowed
38 | /// during key generation
39 | pub fn allow_deprecated() -> bool {
40 | GLOBAL_CONFIG.allow_deprecated.load(Ordering::Relaxed)
41 | }
42 | }
43 |
44 | static GLOBAL_CONFIG: GlobalConfig = GlobalConfig::new();
45 |
46 | pub(super) struct GlobalConfigBuilder {
47 | log_error_details: bool,
48 | buffer_size_limit: Option,
49 | allow_deprecated: bool,
50 | }
51 |
52 | impl GlobalConfigBuilder {
53 | pub fn new() -> Self {
54 | GlobalConfigBuilder {
55 | log_error_details: false,
56 | buffer_size_limit: None,
57 | allow_deprecated: false,
58 | }
59 | }
60 |
61 | pub fn with_log_error_details(mut self, log_error_details: bool) -> Self {
62 | self.log_error_details = log_error_details;
63 |
64 | self
65 | }
66 |
67 | pub fn with_buffer_size_limit(mut self, buffer_size_limit: usize) -> Self {
68 | self.buffer_size_limit = Some(buffer_size_limit);
69 |
70 | self
71 | }
72 |
73 | pub fn with_allow_deprecated(mut self, allow_deprecated: bool) -> Self {
74 | self.allow_deprecated = allow_deprecated;
75 |
76 | self
77 | }
78 |
79 | pub fn build(self) {
80 | GLOBAL_CONFIG
81 | .log_error_details
82 | .store(self.log_error_details, Ordering::Relaxed);
83 | GLOBAL_CONFIG.buffer_size_limit.store(
84 | self.buffer_size_limit.unwrap_or(DEFAULT_BUFFER_SIZE_LIMIT),
85 | Ordering::Relaxed,
86 | );
87 | GLOBAL_CONFIG
88 | .allow_deprecated
89 | .store(self.allow_deprecated, Ordering::Relaxed);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/utils/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! Service utilities
4 | pub mod cli;
5 | pub mod config;
6 | mod global_config;
7 | mod service_builder;
8 | #[cfg(all(
9 | feature = "mbed-crypto-provider",
10 | feature = "pkcs11-provider",
11 | feature = "tpm-provider",
12 | feature = "cryptoauthlib-provider",
13 | feature = "trusted-service-provider",
14 | feature = "direct-authenticator"
15 | ))]
16 | #[cfg(test)]
17 | mod tests;
18 |
19 | pub use global_config::GlobalConfig;
20 | pub use service_builder::ServiceBuilder;
21 |
--------------------------------------------------------------------------------
/src/utils/tests/config/providers_different_type.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "on-disk-manager"
16 | manager_type = "OnDisk"
17 | store_path = "./mappings"
18 |
19 | [[provider]]
20 | provider_type = "MbedCrypto"
21 | key_info_manager = "on-disk-manager"
22 |
23 | [[provider]]
24 | provider_type = "TrustedService"
25 | key_info_manager = "on-disk-manager"
26 |
--------------------------------------------------------------------------------
/src/utils/tests/config/providers_different_type_same_name.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "on-disk-manager"
16 | manager_type = "OnDisk"
17 | store_path = "./mappings"
18 |
19 | [[provider]]
20 | name="a-name"
21 | provider_type = "MbedCrypto"
22 | key_info_manager = "on-disk-manager"
23 |
24 | [[provider]]
25 | name="a-name"
26 | provider_type = "TrustedService"
27 | key_info_manager = "on-disk-manager"
28 |
--------------------------------------------------------------------------------
/src/utils/tests/config/providers_same_type_default_name.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "on-disk-manager"
16 | manager_type = "OnDisk"
17 | store_path = "./mappings"
18 |
19 | [[provider]]
20 | provider_type = "TrustedService"
21 | key_info_manager = "on-disk-manager"
22 |
23 | [[provider]]
24 | provider_type = "TrustedService"
25 | key_info_manager = "on-disk-manager"
26 |
--------------------------------------------------------------------------------
/src/utils/tests/config/providers_same_type_different_name.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "on-disk-manager"
16 | manager_type = "OnDisk"
17 | store_path = "./mappings"
18 |
19 | [[provider]]
20 | name="trusted-service-provider-0"
21 | provider_type = "TrustedService"
22 | key_info_manager = "on-disk-manager"
23 |
24 | [[provider]]
25 | name="trusted-service-provider-1"
26 | provider_type = "TrustedService"
27 | key_info_manager = "on-disk-manager"
28 |
--------------------------------------------------------------------------------
/src/utils/tests/config/providers_same_type_same_name.toml:
--------------------------------------------------------------------------------
1 | [core_settings]
2 | # The CI already timestamps the logs
3 | log_timestamp = false
4 | log_error_details = true
5 |
6 | [listener]
7 | listener_type = "DomainSocket"
8 | timeout = 200 # in milliseconds
9 | socket_path = "/tmp/parsec.sock"
10 |
11 | [authenticator]
12 | auth_type = "Direct"
13 |
14 | [[key_manager]]
15 | name = "on-disk-manager"
16 | manager_type = "OnDisk"
17 | store_path = "./mappings"
18 |
19 | [[provider]]
20 | name="a-name"
21 | provider_type = "TrustedService"
22 | key_info_manager = "on-disk-manager"
23 |
24 | [[provider]]
25 | name="a-name"
26 | provider_type = "TrustedService"
27 | key_info_manager = "on-disk-manager"
28 |
--------------------------------------------------------------------------------
/src/utils/tests/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Contributors to the Parsec project.
2 | // SPDX-License-Identifier: Apache-2.0
3 | //! Static config tests to see if the service starts with different configurations.
4 |
5 | use crate::utils::config::ServiceConfig;
6 | use crate::utils::ServiceBuilder;
7 | use anyhow::anyhow;
8 | use log::error;
9 | use std::env;
10 | use std::io::Error;
11 | use std::io::ErrorKind;
12 |
13 | const CONFIG_TOMLS_FOLDER: &str = "src/utils/tests/config";
14 |
15 | fn config_to_toml(file_name: String) -> ServiceConfig {
16 | let mut new_config_path = env::current_dir() // this is the root of the crate for tests
17 | .unwrap();
18 | new_config_path.push(CONFIG_TOMLS_FOLDER);
19 | new_config_path.push(file_name.clone());
20 | if !new_config_path.exists() {
21 | error!("Configuration file {} does not exist", file_name);
22 | panic!();
23 | }
24 |
25 | let config_file = std::fs::read_to_string(new_config_path.clone())
26 | .map_err(|e| {
27 | error!(
28 | "Failed to read config file from path: {:#?}\nError: {:#?}",
29 | new_config_path, e
30 | );
31 | panic!();
32 | })
33 | .unwrap();
34 | toml::from_str(&config_file)
35 | .map_err(|e| {
36 | error!("Failed to parse service configuration ({})", e);
37 | panic!();
38 | })
39 | .unwrap()
40 | }
41 |
42 | /// Check that the service throws an error when two providers of the same type are started,
43 | /// without setting a name (therefore they have the same default name).
44 | #[test]
45 | fn providers_same_type_default_name() {
46 | let config_path: String = "providers_same_type_default_name.toml".to_string();
47 | let config = config_to_toml(config_path);
48 |
49 | let expected_error = anyhow!(Error::new(
50 | ErrorKind::InvalidData,
51 | "duplicate provider names found"
52 | ));
53 |
54 | let err = ServiceBuilder::build_service(&config).unwrap_err();
55 | assert_eq!(format!("{:#?}", err), format!("{:#?}", expected_error));
56 | }
57 |
58 | /// Check that the service starts when two providers of the same type have different names.
59 | #[test]
60 | fn providers_same_type_different_name() {
61 | let config_path: String = "providers_same_type_different_name.toml".to_string();
62 | let config = config_to_toml(config_path);
63 |
64 | let _ = ServiceBuilder::build_service(&config).unwrap();
65 | }
66 |
67 | /// Check that the service throws an error when two providers of the same type explicitly
68 | /// set the same name.
69 | #[test]
70 | fn providers_same_type_same_name() {
71 | let config_path: String = "providers_same_type_same_name.toml".to_string();
72 | let config = config_to_toml(config_path);
73 |
74 | let expected_error = anyhow!(Error::new(
75 | ErrorKind::InvalidData,
76 | "duplicate provider names found"
77 | ));
78 |
79 | let err = ServiceBuilder::build_service(&config).unwrap_err();
80 | assert_eq!(format!("{:#?}", err), format!("{:#?}", expected_error));
81 | }
82 |
83 | /// Check that the service throws an error when two providers of different types explicitly
84 | /// set the same name.
85 | #[test]
86 | fn providers_different_type_same_name() {
87 | let config_path: String = "providers_different_type_same_name.toml".to_string();
88 | let config = config_to_toml(config_path);
89 |
90 | let expected_error = anyhow!(Error::new(
91 | ErrorKind::InvalidData,
92 | "duplicate provider names found"
93 | ));
94 |
95 | let err = ServiceBuilder::build_service(&config).unwrap_err();
96 | assert_eq!(format!("{:#?}", err), format!("{:#?}", expected_error));
97 | }
98 |
99 | /// Check that the service starts when two providers of different types are declared.
100 | /// (Different default provider names)
101 | #[test]
102 | fn providers_different_type() {
103 | let config_path: String = "providers_different_type.toml".to_string();
104 | let config = config_to_toml(config_path);
105 |
106 | let _ = ServiceBuilder::build_service(&config).unwrap();
107 | }
108 |
--------------------------------------------------------------------------------
/systemd-daemon/parsec.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Parsec Service
3 | Documentation=https://parallaxsecond.github.io/parsec-book/parsec_service/install_parsec_linux.html
4 |
5 | [Service]
6 | WorkingDirectory=/home/parsec/
7 | ExecStart=/usr/libexec/parsec/parsec --config /etc/parsec/config.toml
8 | # Systemd hardening
9 | ProtectSystem=full
10 | ProtectHome=true
11 | ProtectHostname=true
12 | ProtectKernelTunables=true
13 | ProtectKernelModules=true
14 | ProtectKernelLogs=true
15 | ProtectControlGroups=true
16 | RestrictRealtime=true
17 |
18 | [Install]
19 | WantedBy=default.target
20 |
--------------------------------------------------------------------------------
/test/cross-compile.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright 2021 Contributors to the Parsec project.
4 | # SPDX-License-Identifier: Apache-2.0
5 |
6 | set -xeuf -o pipefail
7 |
8 | # The "jwt-svid-authenticator" feature is not included yet because of a cross compilation
9 | # problem of BoringSSL. See https://github.com/tikv/grpc-rs/issues/536. Once resolved,
10 | # "all-authenticators" will be used again.
11 |
12 | # Allow the `pkg-config` crate to cross-compile
13 | export PKG_CONFIG_ALLOW_CROSS=1
14 | # Make the `pkg-config` crate use our wrapper
15 | export PKG_CONFIG=$(pwd)/test/pkg-config
16 |
17 | # Set the SYSROOT used by pkg-config
18 | export SYSROOT=/tmp/arm-linux-gnueabihf
19 | # Add the correct libcrypto to the linking process
20 | export RUSTFLAGS="-lcrypto -L/tmp/arm-linux-gnueabihf/lib"
21 | cargo build --features "pkcs11-provider, mbed-crypto-provider, tpm-provider, unix-peer-credentials-authenticator, direct-authenticator" \
22 | --target armv7-unknown-linux-gnueabihf \
23 | --config 'target.armv7-unknown-linux-gnueabihf.linker="arm-linux-gnueabihf-gcc"'
24 |
25 | export SYSROOT=/tmp/aarch64-linux-gnu
26 | export RUSTFLAGS="-lcrypto -L/tmp/aarch64-linux-gnu/lib"
27 | # Pull in the TS code
28 | git submodule update --init
29 | cargo build --features "pkcs11-provider, mbed-crypto-provider, tpm-provider, trusted-service-provider, unix-peer-credentials-authenticator, direct-authenticator" \
30 | --target aarch64-unknown-linux-gnu \
31 | --config 'target.aarch64-unknown-linux-gnu.linker="aarch64-linux-gnu-gcc"'
32 |
33 | # This is needed because for some reason the i686/i386 libs aren't picked up if we don't toss them around just before...
34 | apt install -y libc6-dev-i386-amd64-cross
35 | export SYSROOT=/tmp/i686-linux-gnu
36 | export RUSTFLAGS="-lcrypto -L/tmp/i686-linux-gnu/lib"
37 | cargo build --features "pkcs11-provider, mbed-crypto-provider, tpm-provider, unix-peer-credentials-authenticator, direct-authenticator, tss-esapi/generate-bindings" --target i686-unknown-linux-gnu
38 |
--------------------------------------------------------------------------------
/test/pkg-config:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export PKG_CONFIG_PATH=
4 | export PKG_CONFIG_LIBDIR=$(SYSROOT)/lib/pkgconfig:${SYSROOT}/usr/lib/pkgconfig:${SYSROOT}/usr/share/pkgconfig:$(SYSROOT)/usr/local/lib/pkgconfig
5 | export PKG_CONFIG_SYSROOT_DIR=${SYSROOT}
6 |
7 | exec pkg-config "$@"
8 |
--------------------------------------------------------------------------------
/utils/release_tracking.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import re
3 | import os
4 | import subprocess
5 | import sys
6 |
7 |
8 | def run_cargo_build(path):
9 | print(f"cargo build, path: {path}")
10 | command = f'cargo build'
11 | return subprocess.check_output(command, shell=True, cwd=path)
12 |
13 |
14 | def run_cargo_update(path, dep):
15 | print(f"cargo update, dep: {dep}")
16 | command = f'cargo update --package {dep}'
17 | return subprocess.check_output(command, shell=True, cwd=path)
18 |
19 |
20 | def git_toml_deps(toml_path, deps_repo_links, deps_branches):
21 | lines = None
22 | with open(toml_path, 'r') as f:
23 | lines = f.readlines()
24 |
25 | to_update = []
26 | output_lines = lines + ['[patch.crates-io]\n']
27 | for line in lines:
28 | for dep in deps_repo_links.keys():
29 | starter = dep + " ="
30 | if line.startswith(starter):
31 | to_update.append(dep)
32 | new_line = f'git = "{deps_repo_links[dep]}", branch = "{deps_branches[dep]}"'
33 | new_line = starter + ' { ' + new_line + ' }\n'
34 | output_lines.append(new_line)
35 |
36 | for updatable in to_update:
37 | run_cargo_update(os.path.dirname(toml_path), updatable)
38 |
39 | with open(toml_path, 'w') as f:
40 | f.writelines(output_lines)
41 | git_cmd = 'git diff'
42 | print(subprocess.check_output(git_cmd,
43 | shell=True,
44 | cwd=os.path.dirname(toml_path)).decode('utf-8'))
45 |
46 |
47 | def main(argv=[], prog_name=''):
48 | parser = argparse.ArgumentParser(prog='ReleaseTracker',
49 | description='Modifies the parsec Cargo.toml files to use the '
50 | 'main branches of parallaxsecond dependencies in '
51 | 'preparation for their publishing and release')
52 | parser.add_argument('paths', nargs='+', help='Absolute paths to the Cargo.toml files')
53 | args = parser.parse_args()
54 |
55 | # The order is important!
56 | parallaxsecond_deps = {
57 | 'psa-crypto-sys': 'rust-psa-crypto',
58 | 'psa-crypto': 'rust-psa-crypto',
59 | 'tss-esapi-sys': 'rust-tss-esapi',
60 | 'tss-esapi': 'rust-tss-esapi',
61 | 'cryptoki-sys': 'rust-cryptoki',
62 | 'cryptoki': 'rust-cryptoki',
63 | 'parsec-interface': 'parsec-interface-rs',
64 | 'parsec-client': 'parsec-client-rust',
65 | }
66 |
67 | repo_links = { repo_name: f"https://github.com/parallaxsecond/{repo_folder}.git" \
68 | for repo_name, repo_folder in parallaxsecond_deps.items() }
69 |
70 | repo_branches = { repo_name: 'main' for repo_name in parallaxsecond_deps.keys() }
71 | repo_branches['tss-esapi-sys'] = '7.x.y'
72 | repo_branches['tss-esapi'] = '7.x.y'
73 |
74 | for path in args.paths:
75 | git_toml_deps(path, repo_links, repo_branches)
76 | run_cargo_build(os.path.dirname(path))
77 |
78 | return 0
79 |
80 |
81 | if __name__ == '__main__':
82 | sys.exit(main(sys.argv[1:], sys.argv[0]))
83 |
--------------------------------------------------------------------------------