├── .github └── workflows │ ├── build.yaml │ ├── ci-tests.yml │ ├── codacy-analysis.yml │ ├── codeql-analysis.yml │ └── shiftleft-analysis.yml ├── .gitignore ├── .gitmodules ├── .golangci.yml ├── LICENSE ├── Makefile ├── README.md ├── e2etest ├── README.md ├── aead_test.go ├── cipher_test.go ├── clients_admin_test.go ├── ginkgomain_test.go ├── management_ops_test.go ├── provider_cfg │ └── all │ │ ├── Dockerfile │ │ └── config.toml ├── scripts │ ├── build-parsec-ci-base.sh │ ├── ci-all.sh │ └── ci.sh ├── signing_test.go ├── testclient_test.go └── unsupported_ops_test.go ├── go.mod ├── go.sum ├── interface ├── README.md ├── auth │ ├── auth_internal_suite_test.go │ ├── auth_internal_test.go │ ├── direct.go │ ├── mod.go │ ├── no_auth.go │ └── unix_peer.go ├── connection │ ├── conn.go │ └── conn_internal_test.go ├── go-protobuf │ └── .gitignore ├── operations │ ├── deleteclient │ │ └── delete_client.pb.go │ ├── listauthenticators │ │ └── list_authenticators.pb.go │ ├── listclients │ │ └── list_clients.pb.go │ ├── listkeys │ │ └── list_keys.pb.go │ ├── listopcodes │ │ └── list_opcodes.pb.go │ ├── listproviders │ │ └── list_providers.pb.go │ ├── operations_client.go │ ├── ping │ │ └── ping.pb.go │ ├── psaaeaddecrypt │ │ └── psa_aead_decrypt.pb.go │ ├── psaaeadencrypt │ │ └── psa_aead_encrypt.pb.go │ ├── psaalgorithm │ │ └── psa_algorithm.pb.go │ ├── psaasymmetricdecrypt │ │ └── psa_asymmetric_decrypt.pb.go │ ├── psaasymmetricencrypt │ │ └── psa_asymmetric_encrypt.pb.go │ ├── psacipherdecrypt │ │ └── psa_cipher_decrypt.pb.go │ ├── psacipherencrypt │ │ └── psa_cipher_encrypt.pb.go │ ├── psadestroykey │ │ └── psa_destroy_key.pb.go │ ├── psaexportkey │ │ └── psa_export_key.pb.go │ ├── psaexportpublickey │ │ └── psa_export_public_key.pb.go │ ├── psageneratekey │ │ └── psa_generate_key.pb.go │ ├── psageneraterandom │ │ └── psa_generate_random.pb.go │ ├── psahashcompare │ │ └── psa_hash_compare.pb.go │ ├── psahashcompute │ │ └── psa_hash_compute.pb.go │ ├── psaimportkey │ │ └── psa_import_key.pb.go │ ├── psakeyattributes │ │ └── psa_key_attributes.pb.go │ ├── psamaccompute │ │ └── psa_mac_compute.pb.go │ ├── psamacverify │ │ └── psa_mac_verify.pb.go │ ├── psarawkeyagreement │ │ └── psa_raw_key_agreement.pb.go │ ├── psasignhash │ │ └── psa_sign_hash.pb.go │ ├── psasignmessage │ │ └── psa_sign_message.pb.go │ ├── psaverifyhash │ │ └── psa_verify_hash.pb.go │ └── psaverifymessage │ │ └── psa_verify_message.pb.go └── requests │ ├── mod.go │ ├── provider.go │ ├── request.go │ ├── requests_internal_suite_test.go │ ├── response.go │ ├── test │ ├── provider_test.go │ ├── request_test.go │ ├── requests_suite_test.go │ └── response_test.go │ ├── wireheader.go │ └── wireheader_internal_test.go ├── mod.go ├── parsec-logo.png ├── parsec ├── algorithm │ ├── aead.go │ ├── algorithm.go │ ├── asymmetric_encryption.go │ ├── asymmetric_signature.go │ ├── cipher.go │ ├── hash.go │ ├── keyagreement.go │ ├── keyderivation.go │ ├── mac.go │ └── test │ │ ├── algorithm_test.go │ │ ├── hash_test.go │ │ └── keyderivation_test.go ├── authenticator.go ├── basicclient.go ├── client_config.go ├── convert_utils.go ├── default_attributes.go ├── keyinfo.go ├── keytype.go ├── mod.go ├── provider.go └── test │ ├── basic_client_test.go │ ├── list_authenticators.json │ ├── list_providers.json │ ├── mocktests │ ├── contstants_test.go │ ├── create_configured_client_test.go │ ├── delete_client_test.go │ ├── list_authenticators_test.go │ ├── list_clients_test.go │ ├── list_providers_test.go │ ├── main_test.go │ └── mock_server_test.go │ └── mod.go └── tmpproto └── github.com └── parallaxsecond └── parsec-client-go └── interface └── operations └── listauthenticators └── list_authenticators.pb.go /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Contributors to the Parsec project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | name: Build and Test 4 | on: [push, pull_request] 5 | 6 | jobs: 7 | golangci: 8 | name: lint 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/setup-go@v3 12 | with: 13 | go-version: 1.18 14 | - uses: actions/checkout@v3 15 | - name: golangci-lint 16 | uses: golangci/golangci-lint-action@v3 17 | with: 18 | # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. 19 | version: v1.50.0 20 | shellcheck: 21 | name: Shellcheck 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Run ShellCheck 26 | uses: ludeeus/action-shellcheck@master 27 | with: 28 | ignore: interface/parsec-operations 29 | test: 30 | name: Test 31 | runs-on: ubuntu-latest 32 | steps: 33 | - name: Set up Go 34 | uses: actions/setup-go@v3 35 | with: 36 | go-version: 1.18 37 | 38 | - name: Check out code 39 | uses: actions/checkout@v3 40 | with: 41 | submodules: recursive 42 | 43 | - name: Run Unit tests. 44 | run: make test-coverage 45 | 46 | # - name: Upload Coverage report to CodeCov 47 | # uses: codecov/codecov-action@v1.0.0 48 | # with: 49 | # token: ${{secrets.CODECOV_TOKEN}} 50 | # file: ./coverage.txt 51 | build: 52 | name: Build 53 | runs-on: ubuntu-latest 54 | needs: [golangci, test] 55 | steps: 56 | - name: Set up Go 57 | uses: actions/setup-go@v3 58 | with: 59 | go-version: 1.16 60 | 61 | - name: Check out code 62 | uses: actions/checkout@v3 63 | with: 64 | submodules: recursive 65 | 66 | - name: Build 67 | run: make build 68 | -------------------------------------------------------------------------------- /.github/workflows/ci-tests.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | all-providers: 7 | name: Various tests targeting a Parsec image with all providers included 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Build Parsec base CI container 12 | run: ./e2etest/scripts/build-parsec-ci-base.sh 13 | - name: Run CI Tests 14 | run: ./e2etest/scripts/ci-all.sh 15 | -------------------------------------------------------------------------------- /.github/workflows/codacy-analysis.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Contributors to the Parsec project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | 5 | # This workflow checks out code, performs a Codacy security scan 6 | # and integrates the results with the 7 | # GitHub Advanced Security code scanning feature. For more information on 8 | # the Codacy security scan action usage and parameters, see 9 | # https://github.com/codacy/codacy-analysis-cli-action. 10 | # For more information on Codacy Analysis CLI in general, see 11 | # https://github.com/codacy/codacy-analysis-cli. 12 | 13 | name: Codacy Security Scan 14 | 15 | on: 16 | push: 17 | pull_request: 18 | 19 | jobs: 20 | codacy-security-scan: 21 | name: Codacy Security Scan 22 | runs-on: ubuntu-latest 23 | steps: 24 | # Checkout the repository to the GitHub Actions runner 25 | - name: Checkout code 26 | uses: actions/checkout@v2 27 | 28 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis 29 | - name: Run Codacy Analysis CLI 30 | uses: codacy/codacy-analysis-cli-action@1.1.0 31 | with: 32 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository 33 | # You can also omit the token and run the tools that support default configurations 34 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 35 | verbose: true 36 | output: results.sarif 37 | format: sarif 38 | # Adjust severity of non-security issues 39 | gh-code-scanning-compat: true 40 | # Force 0 exit code to allow SARIF file generation 41 | # This will handover control about PR rejection to the GitHub side 42 | max-allowed-issues: 2147483647 43 | 44 | # Upload the SARIF file generated in the previous step 45 | - name: Upload SARIF results file 46 | uses: github/codeql-action/upload-sarif@v1 47 | with: 48 | sarif_file: results.sarif 49 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Contributors to the Parsec project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | 5 | # For most projects, this workflow file will not need changing; you simply need 6 | # to commit it to your repository. 7 | # 8 | # You may wish to alter this file to override the set of languages analyzed, 9 | # or to provide custom queries or build logic. 10 | # 11 | # ******** NOTE ******** 12 | # We have attempted to detect the languages in your repository. Please check 13 | # the `language` matrix defined below to confirm you have the correct set of 14 | # supported CodeQL languages. 15 | # ******** NOTE ******** 16 | 17 | name: "CodeQL" 18 | 19 | on: 20 | push: 21 | pull_request: 22 | schedule: 23 | - cron: '44 22 * * 6' 24 | 25 | jobs: 26 | analyze: 27 | name: Analyze 28 | runs-on: ubuntu-latest 29 | 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | language: [ 'go' ] 34 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 35 | # Learn more... 36 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection 37 | 38 | steps: 39 | - name: Checkout repository 40 | uses: actions/checkout@v2 41 | 42 | # Initializes the CodeQL tools for scanning. 43 | - name: Initialize CodeQL 44 | uses: github/codeql-action/init@v1 45 | with: 46 | languages: ${{ matrix.language }} 47 | # If you wish to specify custom queries, you can do so here or in a config file. 48 | # By default, queries listed here will override any specified in a config file. 49 | # Prefix the list here with "+" to use these queries and those in the config file. 50 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 51 | 52 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 53 | # If this step fails, then you should remove it and run the build manually (see below) 54 | - name: Autobuild 55 | uses: github/codeql-action/autobuild@v1 56 | 57 | # ℹ️ Command-line programs to run using the OS shell. 58 | # 📚 https://git.io/JvXDl 59 | 60 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 61 | # and modify them (or add more) to build your code if your project 62 | # uses a compiled language 63 | 64 | #- run: | 65 | # make bootstrap 66 | # make release 67 | 68 | - name: Perform CodeQL Analysis 69 | uses: github/codeql-action/analyze@v1 70 | -------------------------------------------------------------------------------- /.github/workflows/shiftleft-analysis.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Contributors to the Parsec project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | # This workflow integrates Scan with GitHub's code scanning feature 5 | # Scan is a free open-source security tool for modern DevOps teams from ShiftLeft 6 | # Visit https://slscan.io/en/latest/integrations/code-scan for help 7 | name: SL Scan 8 | 9 | # This section configures the trigger for the workflow. Feel free to customize depending on your convention 10 | on: push 11 | 12 | jobs: 13 | Scan-Build: 14 | # Scan runs on ubuntu, mac and windows 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v1 18 | # Instructions 19 | # 1. Setup JDK, Node.js, Python etc depending on your project type 20 | # 2. Compile or build the project before invoking scan 21 | # Example: mvn compile, or npm install or pip install goes here 22 | # 3. Invoke Scan with the github token. Leave the workspace empty to use relative url 23 | 24 | - name: Perform Scan 25 | uses: ShiftLeftSecurity/scan-action@master 26 | env: 27 | WORKSPACE: "" 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | SCAN_AUTO_BUILD: true 30 | with: 31 | output: reports 32 | # Scan auto-detects the languages in your project. To override uncomment the below variable and set the type 33 | # type: credscan,java 34 | # type: python 35 | 36 | - name: Upload report 37 | uses: github/codeql-action/upload-sarif@v1 38 | with: 39 | sarif_file: reports 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | 3 | .devcontainer 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "interface/parsec-operations"] 2 | path = interface/parsec-operations 3 | url = https://github.com/parallaxsecond/parsec-operations 4 | [submodule "mock-test/parsec-mock"] 5 | path = mock-test/parsec-mock 6 | url = https://github.com/parallaxsecond/parsec-mock 7 | 8 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Contributors to the Parsec project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | linters-settings: 5 | depguard: 6 | list-type: blacklist 7 | # packages: 8 | # # logging is allowed only by logutils.Log, logrus 9 | # # is allowed to use only in logutils package 10 | # - github.com/sirupsen/logrus 11 | # packages-with-error-message: 12 | # - github.com/sirupsen/logrus: "logging is allowed only by logutils.Log" 13 | dupl: 14 | threshold: 100 15 | funlen: 16 | lines: 100 17 | statements: 50 18 | gci: 19 | local-prefixes: github.com/golangci/golangci-lint 20 | goconst: 21 | min-len: 2 22 | min-occurrences: 2 23 | gocritic: 24 | enabled-tags: 25 | - diagnostic 26 | - experimental 27 | - opinionated 28 | - performance 29 | - style 30 | disabled-checks: 31 | - dupImport # https://github.com/go-critic/go-critic/issues/845 32 | - ifElseChain 33 | - octalLiteral 34 | - whyNoLint 35 | - wrapperFunc 36 | gocyclo: 37 | min-complexity: 15 38 | goimports: 39 | local-prefixes: github.com/golangci/golangci-lint 40 | gomnd: 41 | settings: 42 | mnd: 43 | # don't include the "operation" and "assign" 44 | checks: argument,case,condition,return 45 | govet: 46 | check-shadowing: true 47 | settings: 48 | printf: 49 | funcs: 50 | - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof 51 | - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf 52 | - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf 53 | - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf 54 | lll: 55 | line-length: 140 56 | maligned: 57 | suggest-new: true 58 | misspell: 59 | # locale: UK 60 | nolintlint: 61 | allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) 62 | allow-unused: false # report any unused nolint directives 63 | require-explanation: false # don't require an explanation for nolint directives 64 | require-specific: false # don't require nolint directives to be specific about which linter is being skipped 65 | 66 | linters: 67 | # please, do not use `enable-all`: it's deprecated and will be removed soon. 68 | # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint 69 | disable-all: true 70 | enable: 71 | - bodyclose 72 | - depguard 73 | - dogsled 74 | - errcheck 75 | - exhaustive 76 | - exportloopref 77 | - gochecknoinits 78 | - goconst 79 | - gocritic 80 | - gocyclo 81 | - gofmt 82 | - goimports 83 | - gomnd 84 | - goprintffuncname 85 | - gosec 86 | - gosimple 87 | - govet 88 | - ineffassign 89 | - misspell 90 | - nakedret 91 | - noctx 92 | - nolintlint 93 | - revive 94 | - rowserrcheck 95 | - staticcheck 96 | - stylecheck 97 | - typecheck 98 | - unconvert 99 | - unparam 100 | - unused 101 | - whitespace 102 | 103 | # don't enable: 104 | # - dupl 105 | # - funlen 106 | # - asciicheck 107 | # - gochecknoglobals 108 | # - gocognit 109 | # - godot 110 | # - godox 111 | # - goerr113 112 | # - interfacer 113 | # - lll 114 | # - maligned 115 | # - nestif 116 | # - prealloc 117 | # - testpackage 118 | # - wsl 119 | 120 | issues: 121 | # Excluding configuration per-path, per-linter, per-text and per-source 122 | exclude-rules: 123 | - path: _test\.go 124 | linters: 125 | - gomnd 126 | 127 | # https://github.com/go-critic/go-critic/issues/926 128 | - linters: 129 | - gocritic 130 | text: "unnecessaryDefer:" 131 | 132 | 133 | run: 134 | skip-dirs: 135 | - test/testdata_etc 136 | - internal/cache 137 | - internal/renameio 138 | - internal/robustio 139 | 140 | # golangci.com configuration 141 | # https://github.com/golangci/golangci/wiki/Configuration 142 | service: 143 | golangci-lint-version: 1.35.x # use the fixed version to not introduce new linters unexpectedly 144 | prepare: 145 | - echo "here I can run custom commands, but no preparation needed for this repo" -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Contributors to the Parsec project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | PROJECT_NAME := "parsec-client-go" 5 | PKG := "github.com/parallaxsecond/$(PROJECT_NAME)" 6 | PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/) 7 | GO_FILES := $(shell find . -name '*.go' | grep -v /vendor/ | grep -v _test.go) 8 | 9 | 10 | PROTOC_PREPROCESSED_FILES := $(shell find ./interface/parsec-operations/protobuf -name '*.proto' -exec basename {} \; | awk '{print "interface/go-protobuf/"$$1}') 11 | PROTOC_OUTPUT_FILES=$(shell find interface/parsec-operations/protobuf/ -name "*.proto" -exec basename {} .proto \; | awk '{print "interface/operations/"$$1".pb.go"}') 12 | 13 | .PHONY: all dep lint vet test test-coverage build protoc protobuf_preprocess clean-protobuf clean clean-all 14 | 15 | protobuf_preprocess: ${PROTOC_PREPROCESSED_FILES} 16 | 17 | protoc: protobuf_preprocess ${PROTOC_OUTPUT_FILES} ## Generate protocol buffer go code 18 | 19 | interface/go-protobuf/%.proto: interface/parsec-operations/protobuf/%.proto 20 | @mkdir -p interface/go-protobuf 21 | @cp $< $@ 22 | @$(eval PKG_NAME := $(shell basename $< .proto | sed s/_//g)) 23 | @$(eval PKG_DEF := $(shell echo "option go_package = \\\"github.com/parallaxsecond/parsec-client-go/interface/operations/$(PKG_NAME)\\\";")) 24 | @#echo gopkg $(PKG_DEF) 25 | @grep "$(PKG_DEF)" $@ || echo "\n$(PKG_DEF)" >> $@ 26 | 27 | 28 | # Can't work out how to get path and filename into the match 29 | # need to have operations/option/option.pb.go maping to interface/go-protobuf/option.proto 30 | # But works quickly and not needed often 31 | interface/operations/%.pb.go: interface/go-protobuf/%.proto 32 | @mkdir -p tmp/protoout 33 | @protoc -I=interface/go-protobuf --go_out=tmp/protoout $< > /dev/null 34 | @$(eval PKG_NAME := $(shell basename $< .proto | sed s/_//g)) 35 | @rm -Rf "./interface/operations/$(PKG_NAME)" 36 | @mv "tmp/protoout/github.com/parallaxsecond/parsec-client-go/interface/operations/$(PKG_NAME)" ./interface/operations 37 | @rm -Rf tmp/ 38 | 39 | clean-all: clean clean-protobuf 40 | clean: 41 | @go clean ./... 42 | @rm -f $(PROJECT_NAME)/buildmk 43 | 44 | clean-protobuf: 45 | @find interface/operations/ -name "*.pb.go" -exec rm {} \; 46 | @rm -Rf interface/go-protobuf/* 47 | 48 | 49 | all: protoc build ## Generate protocol buffer code and compile 50 | 51 | dep: ## Get the dependencies 52 | @go mod download 53 | 54 | lint: ## Lint Golang files and shellcheck scripts 55 | @golangci-lint run 56 | # Omit interface/parsec-operations as it is from a different repo and is loaded as submodule 57 | @find . -path ./interface/parsec-operations -prune -false -o -name "*.sh" | xargs shellcheck 58 | 59 | test: ## Run unittests 60 | @go test -short ${PKG_LIST} | grep -v 'no test files' 61 | 62 | test-coverage: ## Run tests with coverage 63 | @go test -short -coverprofile cover.out -covermode=atomic ${PKG_LIST} 64 | @cat cover.out >> coverage.txt 65 | 66 | ci-test-all: ## Run Continuous Integration tests for all providers 67 | @./e2etest/scripts/ci-all.sh 68 | 69 | build: dep ## Build the binary file 70 | @go build -i -o ./... $(PKG) 71 | 72 | 73 | 74 | 75 | help: ## Display this help screen 76 | @grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 18 | 19 | ![PARSEC logo](./parsec-logo.png) 20 | # PARSEC Go Client 21 | 22 | This repository contains a PARSEC Go Client library. 23 | The library contains methods to communicate using the [wire protocol](https://parallaxsecond.github.io/parsec-book/parsec_client/wire_protocol.html). 24 | 25 | --- 26 | :imp:**WARNING** 27 | 28 | The current status of this interface is suitable only for review of the API. It is a work in progress. There are ommissions and testing is very minimal at this stage. 29 | 30 | --- 31 | 32 | # Build Status 33 | [![Build and Test](https://github.com/parallaxsecond/parsec-client-go/actions/workflows/build.yaml/badge.svg)](https://github.com/parallaxsecond/parsec-client-go/actions/workflows/build.yaml) 34 | [![Continuous Integration](https://github.com/parallaxsecond/parsec-client-go/actions/workflows/ci-tests.yml/badge.svg)](https://github.com/parallaxsecond/parsec-client-go/actions/workflows/ci-tests.yml) 35 | # Usage 36 | 37 | Sample usage can be found in the end to end tests in the [e2etest folder](https://github.com/parallaxsecond/parsec-client-go/tree/master/e2etest) 38 | 39 | # Parsec Service Socket Configuration 40 | 41 | This client will, connect to the parsec service on a URL defined using the PARSEC_SERVICE_ENDPOINT environment variable. This URL must be for the unix scheme (no other schemes are supported at this time). 42 | 43 | If the PARSEC_SERVICE_ENDPOINT environment variable is not set, then the default value of unix:/run/parsec/parsec.sock is used. 44 | 45 | 46 | # Parsec Interface Version 47 | 48 | The parsec interface is defined in google protocol buffers .proto files, included in the [parsec operations](https://github.com/parallaxsecond/parsec-operations), which is included as a git submodule in the [interface/parsec-operations](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/parsec-operations) folder in this repository. This submodule is currently pinned to parsec-operations v0.6.0 49 | 50 | The protocol buffers files are used to [generate translation golang code](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/operations) which is checked into this repository to remove the requirement for developers *using* this library to install protoc. 51 | 52 | ## Interface Generation 53 | 54 | ### Prerequisites 55 | You will need [protoc 3+ installed](https://grpc.io/docs/protoc-installation/) as well as gcc. 56 | 57 | You will also need the [go plugin for protoc](https://grpc.io/docs/languages/go/quickstart/) 58 | 59 | On ubuntu 20.04, the following will install the tools you need: 60 | ```bash 61 | # protoc and gcc 62 | apt-get install protoc build-essential 63 | # go plugin 64 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 65 | ``` 66 | 67 | ### Generation 68 | 69 | To update the generated files, run the following in this folder (protoc and make required) 70 | 71 | ``` 72 | make clean-protobuf 73 | make protoc 74 | make build 75 | ``` 76 | 77 | # Testing 78 | 79 | To run unit tests: 80 | 81 | ``` 82 | make test 83 | ``` 84 | 85 | To run continuous integration tests (requires docker). This will run up docker container that will run the parsec daemon and then run a series of end to end tests. 86 | 87 | ``` 88 | make ci-test-all 89 | # can also be run using 90 | ./e2etest/scripts/ci-all.sh 91 | ``` 92 | 93 | All code for the end to end tests is in the [e2etest](https://github.com/parallaxsecond/parsec-client-go/tree/master/e2etest) folder. 94 | 95 | Black box unit tests for folders are found in a test folder under the main package folder (e.g. for algorithm [parsec/algorithm/test](https://github.com/parallaxsecond/parsec-client-go/tree/master/parsec/algorithm/test)) 96 | 97 | Internal tests for packages will be in the relevant package folders as required by go, and will be called xxx_internal_test.go 98 | 99 | # Folder Structure 100 | 101 | - **This folder** General files that must be at the top level - readmes, licence, lint configurations, etc. 102 | - [.github/workflows](https://github.com/parallaxsecond/parsec-client-go/tree/master/.github/workflows) Github Build CI action definitions - CI testing, build, unit test, static analysis... 103 | - [e2etest](https://github.com/parallaxsecond/parsec-client-go/tree/master/e2etest) End to End testing - Docker containers to fire up parsec and run end to end tests. Also used in CI end to end testing. 104 | - [interface](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface) The Google Protocol Buffers basic client for communicating with the parsec daemon. This provides the underlying interface to parsec, but is not intended for client application use. 105 | - [parsec](https://github.com/parallaxsecond/parsec-client-go/tree/master/parsec) This is the public interface of the Parsec Go client. 106 | 107 | # License 108 | 109 | The software is provided under Apache-2.0. Contributions to this project are accepted under the same license. 110 | 111 | This project uses the following third party libraries: 112 | - golang.org/x/sys BSD-3-Clause 113 | - google.golang.org/protobuf BSD-3-Clause 114 | - github.com/sirupsen/logrus MIT 115 | 116 | 117 | # Contributing 118 | 119 | Please check the [Contributing](CONTRIBUTING.md) to know more about the contribution process. 120 | -------------------------------------------------------------------------------- /e2etest/README.md: -------------------------------------------------------------------------------- 1 | # Parsec Go Client End to End (Continuous Integration) tests 2 | 3 | Currently only the CI test with all providers enabled is working at all. To run it, you will need docker. 4 | 5 | ```bash 6 | ./scripts/ci-all.sh 7 | ``` 8 | 9 | The ci-*.sh scripts in the scripts folder all build docker images defined in the provider_cfg folder, which has subfolders for each of the provider configurations. 10 | 11 | The docker containers run the ci.sh script in the scripts folder. -------------------------------------------------------------------------------- /e2etest/aead_test.go: -------------------------------------------------------------------------------- 1 | // +build end2endtest 2 | 3 | // Copyright 2021 Contributors to the Parsec project. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | package e2etest 7 | 8 | import ( 9 | "bytes" 10 | "testing" 11 | 12 | parsec "github.com/parallaxsecond/parsec-client-go/parsec" 13 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 14 | ) 15 | 16 | func TestAead(t *testing.T) { 17 | 18 | f := initFixture(t) 19 | defer f.closeFixture(t) 20 | f.c.SetImplicitProvider(parsec.ProviderMBed) 21 | 22 | const keyname = "cipher_symm_key" 23 | keyAttrs := &parsec.KeyAttributes{ 24 | KeyBits: 256, 25 | KeyType: parsec.NewKeyType().Aes(), 26 | KeyPolicy: &parsec.KeyPolicy{ 27 | KeyAlgorithm: algorithm.NewAead().Aead(algorithm.AeadAlgorithmGCM), 28 | KeyUsageFlags: &parsec.UsageFlags{ 29 | Cache: false, 30 | Copy: false, 31 | Decrypt: true, 32 | Derive: false, 33 | Encrypt: true, 34 | Export: false, 35 | SignHash: false, 36 | SignMessage: false, 37 | VerifyHash: false, 38 | VerifyMessage: false, 39 | }, 40 | }, 41 | } 42 | 43 | err := f.c.PsaGenerateKey(keyname, keyAttrs) 44 | if err != nil { 45 | t.Fatal(err) 46 | } 47 | f.deferredKeyDestroy(keyname) 48 | 49 | plaintext := "the quick brown fox" 50 | nonce := []byte("nonce") 51 | additionalData := []byte("extradata") 52 | ciphertext, err := f.c.PsaAeadEncrypt(keyname, keyAttrs.KeyPolicy.KeyAlgorithm.GetAead(), nonce, additionalData, []byte(plaintext)) 53 | 54 | if err != nil { 55 | t.Fatal(err) 56 | } 57 | if bytes.Compare(ciphertext, []byte(plaintext)) == 0 { 58 | t.Fatalf("ciphertext should not be same as plaintext") 59 | } 60 | 61 | plaintext2, err := f.c.PsaAeadDecrypt(keyname, keyAttrs.KeyPolicy.KeyAlgorithm.GetAead(), nonce, additionalData, ciphertext) 62 | 63 | if err != nil { 64 | t.Fatal(err) 65 | } 66 | if bytes.Equal(ciphertext, plaintext2) { 67 | t.Fatalf("ciphertext should not be same as plaintext") 68 | } 69 | if !bytes.Equal([]byte(plaintext), plaintext2) { 70 | t.Fatalf("plaintext retrieved from decrypting ciphertext not same as original. Got %v, expected %v", plaintext2, []byte(plaintext)) 71 | } 72 | 73 | // test with changed nonce, should fail 74 | plaintext2, err = f.c.PsaAeadDecrypt(keyname, keyAttrs.KeyPolicy.KeyAlgorithm.GetAead(), []byte("newnonce"), additionalData, ciphertext) 75 | if err == nil { 76 | t.Fatal("Expected decrypt to fail if using wrong nonce") 77 | } 78 | 79 | // test with changed additional data, should fail 80 | plaintext2, err = f.c.PsaAeadDecrypt(keyname, keyAttrs.KeyPolicy.KeyAlgorithm.GetAead(), nonce, []byte("fakedata"), ciphertext) 81 | if err == nil { 82 | t.Fatal("Expected decrypt to fail if using wrong additional data") 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /e2etest/cipher_test.go: -------------------------------------------------------------------------------- 1 | // +build unsupported_test 2 | 3 | // Copyright 2021 Contributors to the Parsec project. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | package e2etest 7 | 8 | import ( 9 | "bytes" 10 | "testing" 11 | 12 | parsec "github.com/parallaxsecond/parsec-client-go/parsec" 13 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 14 | ) 15 | 16 | func TestCipherEncrypt(t *testing.T) { 17 | 18 | f := initFixture(t) 19 | defer f.closeFixture(t) 20 | 21 | const keyname = "cipher_symm_key" 22 | keyAttrs := &parsec.KeyAttributes{ 23 | KeyBits: 256, 24 | KeyType: parsec.NewKeyType().Aes(), 25 | KeyPolicy: &parsec.KeyPolicy{ 26 | KeyAlgorithm: algorithm.NewCipher(algorithm.CipherModeCFB), 27 | KeyUsageFlags: &parsec.UsageFlags{ 28 | Cache: false, 29 | Copy: false, 30 | Decrypt: true, 31 | Derive: false, 32 | Encrypt: true, 33 | Export: false, 34 | SignHash: false, 35 | SignMessage: false, 36 | VerifyHash: false, 37 | VerifyMessage: false, 38 | }, 39 | }, 40 | } 41 | 42 | err := f.c.PsaGenerateKey(keyname, keyAttrs) 43 | if err != nil { 44 | t.Fatal(err) 45 | } 46 | f.deferredKeyDestroy(keyname) 47 | 48 | plaintext := "the quick brown fox" 49 | 50 | ciphertext, err := f.c.PsaCipherEncrypt(keyname, keyAttrs.KeyPolicy.KeyAlgorithm.GetCipher(), []byte(plaintext)) 51 | 52 | if err != nil { 53 | t.Fatal(err) 54 | } 55 | if bytes.Compare(ciphertext, []byte(plaintext)) == 0 { 56 | t.Fatalf("ciphertext should not be same as plaintext") 57 | } 58 | 59 | plaintext2, err := f.c.PsaCipherDecrypt(keyname, keyAttrs.KeyPolicy.KeyAlgorithm.GetCipher(), ciphertext) 60 | 61 | if err != nil { 62 | t.Fatal(err) 63 | } 64 | if bytes.Compare(ciphertext, plaintext2) == 0 { 65 | t.Fatalf("ciphertext should not be same as plaintext") 66 | } 67 | if bytes.Compare([]byte(plaintext), plaintext2) == 0 { 68 | t.Fatalf("plaintext retrieved from decrypting ciphertext not same as original. Got %v, expected %v", plaintext2, plaintext) 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /e2etest/clients_admin_test.go: -------------------------------------------------------------------------------- 1 | //go:build end2endtest 2 | // +build end2endtest 3 | 4 | // Copyright 2021 Contributors to the Parsec project. 5 | // SPDX-License-Identifier: Apache-2.0 6 | package e2etest 7 | 8 | import ( 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | parsec "github.com/parallaxsecond/parsec-client-go/parsec" 12 | ) 13 | 14 | var _ = Describe("admin mode client management operations", func() { 15 | var ( 16 | basicClient *parsec.BasicClient 17 | err error 18 | ) 19 | BeforeEach(func() { 20 | basicClient, err = parsec.CreateConfiguredClient( 21 | parsec.NewClientConfig().Authenticator(parsec.NewUnixPeerAuthenticator()), 22 | ) 23 | Expect(err).NotTo(HaveOccurred()) 24 | }) 25 | 26 | Describe("delete keys by deleting client", func() { 27 | It("should succeed if we delete client and we should have no keys remaining", func() { 28 | // As we're root user, should be able to list clients 29 | clients, err := basicClient.ListClients() 30 | Expect(err).NotTo(HaveOccurred()) 31 | // We'll delete any clients (should succeed if there are any) 32 | for _, client := range clients { 33 | err = basicClient.DeleteClient(client) 34 | Expect(err).NotTo(HaveOccurred()) 35 | } 36 | 37 | // Check there are no keys present 38 | keyinfarr, err := basicClient.ListKeys() 39 | Expect(err).NotTo(HaveOccurred()) 40 | Expect(len(keyinfarr)).To(Equal(0)) 41 | 42 | // Create a key 43 | err = basicClient.PsaGenerateKey("key1", parsec.DefaultKeyAttribute().SigningKey()) 44 | Expect(err).NotTo(HaveOccurred()) 45 | 46 | // Check it is there 47 | keyinfarr, err = basicClient.ListKeys() 48 | Expect(err).NotTo(HaveOccurred()) 49 | Expect(len(keyinfarr)).To(Equal(1)) 50 | 51 | // Check we have one client 52 | clients, err = basicClient.ListClients() 53 | Expect(err).NotTo(HaveOccurred()) 54 | Expect(len(clients)).To(Equal(1)) 55 | 56 | // Delete the client 57 | err = basicClient.DeleteClient(clients[0]) 58 | Expect(err).NotTo(HaveOccurred()) 59 | 60 | // Check we hae no keys left 61 | keyinfarr, err = basicClient.ListKeys() 62 | Expect(err).NotTo(HaveOccurred()) 63 | Expect(len(keyinfarr)).To(Equal(0)) 64 | }) 65 | 66 | }) 67 | AfterEach(func() { 68 | if basicClient != nil { 69 | basicClient.Close() 70 | } 71 | }) 72 | }) 73 | -------------------------------------------------------------------------------- /e2etest/ginkgomain_test.go: -------------------------------------------------------------------------------- 1 | //go:build end2endtest 2 | // +build end2endtest 3 | 4 | // Copyright 2021 Contributors to the Parsec project. 5 | // SPDX-License-Identifier: Apache-2.0 6 | 7 | package e2etest 8 | 9 | // Test case to run Ginkgo tests 10 | 11 | import ( 12 | "testing" 13 | 14 | . "github.com/onsi/ginkgo" 15 | . "github.com/onsi/gomega" 16 | ) 17 | 18 | func TestRequests(t *testing.T) { 19 | RegisterFailHandler(Fail) 20 | RunSpecs(t, "requests package internal suite") 21 | } 22 | -------------------------------------------------------------------------------- /e2etest/management_ops_test.go: -------------------------------------------------------------------------------- 1 | // +build end2endtest 2 | 3 | // Copyright 2021 Contributors to the Parsec project. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | package e2etest 7 | 8 | import ( 9 | "testing" 10 | 11 | parsec "github.com/parallaxsecond/parsec-client-go/parsec" 12 | ) 13 | 14 | func TestInitialiseClient(t *testing.T) { 15 | c, err := parsec.CreateConfiguredClient("ci test app") 16 | if err != nil { 17 | t.Fatal(err) 18 | return 19 | } 20 | 21 | err = c.Close() 22 | if err != nil { 23 | t.Fatal(err) 24 | return 25 | } 26 | } 27 | 28 | func TestPing(t *testing.T) { 29 | f := initFixture(t) 30 | defer f.closeFixture(t) 31 | 32 | majver, minver, err := f.c.Ping() 33 | if err != nil { 34 | t.Fatalf("got an error from ping: %v", err) 35 | } 36 | if majver != 1 && minver != 0 { 37 | t.Fatalf("Expected version 1.0, got %v,%v", majver, minver) 38 | } 39 | } 40 | func TestManageKeys(t *testing.T) { 41 | f := initFixture(t) 42 | defer f.closeFixture(t) 43 | 44 | if f.c.GetImplicitProvider() != parsec.ProviderPKCS11 { 45 | t.Fatalf("expected to have pkcs11 provider, got %v", f.c.GetImplicitProvider()) 46 | } 47 | // Create a new key 48 | const keyName = "testManageKeys" 49 | kattrs := parsec.DefaultKeyAttribute().SigningKey() 50 | if kattrs == nil { 51 | t.Fatal("got nil key attributes") 52 | } 53 | err := f.c.PsaGenerateKey(keyName, kattrs) 54 | if err != nil { 55 | t.Fatal(err) 56 | } 57 | 58 | f.deferredKeyDestroy(keyName) 59 | 60 | // Created key, see if we can see it with list keys 61 | keyList, err := f.c.ListKeys() 62 | if err != nil { 63 | t.Fatal(err) 64 | } 65 | if keyList == nil { 66 | t.Fatal("returned nil key list") 67 | } 68 | var foundKey *parsec.KeyInfo 69 | for _, kinfo := range keyList { 70 | if kinfo.Name == keyName { 71 | foundKey = kinfo 72 | } 73 | } 74 | if foundKey == nil { 75 | t.Errorf("Could not find created key in list_keys result %v", keyName) 76 | } 77 | if !t.Failed() { 78 | // TODO really need to fix types in return structure 79 | if foundKey.ProviderID != parsec.ProviderPKCS11 { 80 | t.Errorf("Expected key to have PKCS11 provider, instead found %v", foundKey.ProviderID) 81 | } 82 | } 83 | // And destroy the key - we want to test it gets destroyed without error here 84 | err = f.c.PsaDestroyKey(keyName) 85 | if err != nil { 86 | t.Fatal(err) 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /e2etest/provider_cfg/all/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Contributors to the Parsec project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | FROM parsec-ci-service-test-all 5 | 6 | # Install Rust toolchain for root 7 | USER root 8 | 9 | WORKDIR /tmp 10 | 11 | # Install go 1.18 12 | 13 | RUN curl -s -N -L https://golang.org/dl/go1.18.linux-amd64.tar.gz | tar xz -C /usr/local 14 | ENV PATH="/usr/local/go/bin:${PATH}" 15 | 16 | RUN git clone https://github.com/parallaxsecond/parsec 17 | 18 | WORKDIR parsec 19 | # Initialising any submodules. Currently used for building the Trusted Service provider 20 | RUN git submodule update --init 21 | RUN RUST_LOG=info RUST_BACKTRACE=1 cargo build --features=all-providers,all-authenticators 22 | 23 | WORKDIR /tmp -------------------------------------------------------------------------------- /e2etest/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 = "/run/parsec/parsec.sock" 14 | 15 | [authenticator] 16 | #auth_type = "Direct" 17 | auth_type = "UnixPeerCredentials" 18 | #workload_endpoint="unix:///tmp/agent.sock" 19 | admins = [ { name = "0" } ] 20 | 21 | [[key_manager]] 22 | name = "on-disk-manager" 23 | manager_type = "OnDisk" 24 | store_path = "./mappings" 25 | 26 | [[provider]] 27 | provider_type = "MbedCrypto" 28 | key_info_manager = "on-disk-manager" 29 | 30 | [[provider]] 31 | provider_type = "Tpm" 32 | key_info_manager = "on-disk-manager" 33 | tcti = "mssim" 34 | owner_hierarchy_auth = "tpm_pass" 35 | 36 | [[provider]] 37 | provider_type = "Pkcs11" 38 | key_info_manager = "on-disk-manager" 39 | library_path = "/usr/local/lib/softhsm/libsofthsm2.so" 40 | user_pin = "123456" 41 | # The slot_number field is optional and when not present the first used slot will be used 42 | # slot_number 43 | -------------------------------------------------------------------------------- /e2etest/scripts/build-parsec-ci-base.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Contributors to the Parsec project. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | # Builds the main parsec ci test docker image 7 | # and tags it for local use 8 | 9 | set -e 10 | 11 | PARSEC_CI_DOCKER_IMAGE_TAG=parsec-ci-service-test-all 12 | 13 | cleanup() { 14 | echo "Cleaning up" 15 | popd 16 | if [[ -n "${PARSEC_CI_FOLDER}" ]] 17 | then 18 | if [ -d "${PARSEC_CI_FOLDER}" ] 19 | then 20 | rm -Rf "${PARSEC_CI_FOLDER}" 21 | fi 22 | fi 23 | 24 | } 25 | 26 | trap cleanup EXIT 27 | 28 | PARSEC_CI_FOLDER=$(mktemp -d) 29 | 30 | # Get the docker file and associated scripts from main branch on parsec server repo 31 | PARSEC_DOCKER_FILES_BASE=https://raw.githubusercontent.com/parallaxsecond/parsec/main/e2e_tests/docker_image/ 32 | 33 | pushd "${PARSEC_CI_FOLDER}" 34 | 35 | wget -q ${PARSEC_DOCKER_FILES_BASE}/_exec_wrapper 36 | wget -q ${PARSEC_DOCKER_FILES_BASE}/cross-compile-tss.sh 37 | wget -q ${PARSEC_DOCKER_FILES_BASE}/generate-keys.sh 38 | wget -q ${PARSEC_DOCKER_FILES_BASE}/import-old-e2e-tests.sh 39 | wget -q ${PARSEC_DOCKER_FILES_BASE}/parsec-service-test-all.Dockerfile 40 | chmod +x _exec_wrapper ./*.sh 41 | 42 | # and build the image 43 | docker build -t "${PARSEC_CI_DOCKER_IMAGE_TAG}" -f parsec-service-test-all.Dockerfile . 44 | 45 | -------------------------------------------------------------------------------- /e2etest/scripts/ci-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2021 Contributors to the Parsec project. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | # Run various tests against parsec daemon in a docker container 7 | 8 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 9 | TESTDIR=$(realpath "${SCRIPTDIR}"/..) 10 | 11 | set -eouf pipefail 12 | 13 | pushd "${TESTDIR}" 14 | docker build -t all-providers "${TESTDIR}"/provider_cfg/all 15 | docker run -v "$(realpath "${TESTDIR}"/..)":/tmp/parsecgo -w /tmp/parsecgo all-providers /tmp/parsecgo/e2etest/scripts/ci.sh all 16 | popd -------------------------------------------------------------------------------- /e2etest/scripts/ci.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2021 Contributors to the Parsec project. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | # Run parsec daemon and then run test suites as defined by parameters (either all providers or a single provider) 7 | # This script is run by the docker based ci build environment and is not intended to be run separately 8 | # To run this for all provider tests, run ./ci-all.sh in this folder (you will need docker installed) 9 | 10 | 11 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 12 | TESTDIR=$(realpath "${SCRIPTDIR}"/..) 13 | set -ex 14 | 15 | # The clean up procedure is called when the script finished or is interrupted 16 | cleanup () { 17 | echo "Shutdown Parsec and clean up" 18 | # Stop Parsec if running 19 | stop_service 20 | # Stop tpm_server if running 21 | if [ -n "$TPM_SRV_PID" ]; then kill "$TPM_SRV_PID" || true; fi 22 | if [ -n "$TPM_MC_SRV_PID" ]; then kill "$TPM_MC_SRV_PID" || true; fi 23 | # Remove the slot_number line added earlier 24 | find e2etest -name "*toml" -not -name "Cargo.toml" -exec sed -i 's/^slot_number =.*/# slot_number/' {} \; 25 | find e2etest -name "*toml" -not -name "Cargo.toml" -exec sed -i 's/^serial_number =.*/# serial_number/' {} \; 26 | # Remove fake mapping and temp files 27 | rm -rf "mappings" "kim-mappings" 28 | rm -f "NVChip" 29 | rm -f "e2etest/provider_cfg/tmp_config.toml" 30 | rm -f "parsec.sock" 31 | 32 | if [ -z "$NO_GO_CLEAN" ]; then go clean; fi 33 | } 34 | 35 | usage () { 36 | printf " 37 | Continuous Integration test script 38 | 39 | This script will execute various tests targeting a platform with a 40 | single provider or all providers included. 41 | It is meant to be executed inside one of the container 42 | which Dockerfiles are in tests/per_provider/provider_cfg/*/ 43 | or tests/all_providers/ 44 | 45 | Usage: ./ci.sh [--no-go-clean] [--no-stress-test] PROVIDER_NAME 46 | where PROVIDER_NAME can be one of: 47 | - mbed-crypto 48 | - pkcs11 49 | - tpm 50 | - all 51 | " 52 | } 53 | 54 | error_msg () { 55 | echo "Error: $1" 56 | usage 57 | exit 1 58 | } 59 | 60 | wait_for_service() { 61 | while [ -z "$(pgrep parsec)" ]; do 62 | sleep 1 63 | done 64 | 65 | sleep 5 66 | 67 | # Check that Parsec successfully started and is running 68 | pgrep parsec >/dev/null 69 | } 70 | 71 | stop_service() { 72 | # Randomly signals with SIGINT or SIGTERM to test that both can be used to 73 | # gracefully shutdowm Parsec. 74 | # shellcheck disable=SC2004 75 | if ! (($RANDOM % 2)); then 76 | pkill -SIGINT parsec || true 77 | else 78 | pkill -SIGTERM parsec || true 79 | fi 80 | 81 | while [ -n "$(pgrep parsec)" ]; do 82 | sleep 1 83 | done 84 | } 85 | 86 | reset_tpm() 87 | { 88 | # In order to reset the TPM, we need to restart the TPM server and send a Startup(CLEAR) 89 | pkill tpm_server 90 | sleep 1 91 | 92 | tpm_server & 93 | TPM_SRV_PID=$! 94 | sleep 5 95 | 96 | tpm2_startup -c -T mssim 97 | } 98 | 99 | reload_service() { 100 | echo "Trigger a configuration reload to load the new mappings or config file" 101 | pkill -SIGHUP parsec 102 | sleep 5 103 | } 104 | 105 | # Parse arguments 106 | PROVIDER_NAME= 107 | CONFIG_PATH=${TESTDIR}/provider_cfg/tmp_config.toml 108 | while [ "$#" -gt 0 ]; do 109 | case "$1" in 110 | mbed-crypto | pkcs11 | tpm | all ) 111 | if [ -n "$PROVIDER_NAME" ]; then 112 | error_msg "Only one provider name must be given" 113 | fi 114 | PROVIDER_NAME=$1 115 | cp "${TESTDIR}"/provider_cfg/"$1"/config.toml "$CONFIG_PATH" 116 | ;; 117 | *) 118 | error_msg "Unknown argument: $1" 119 | ;; 120 | esac 121 | shift 122 | done 123 | 124 | # Check if the PROVIDER_NAME was given. 125 | if [ -z "$PROVIDER_NAME" ]; then 126 | error_msg "a provider name needs to be given as input argument to that script." 127 | fi 128 | 129 | trap cleanup EXIT 130 | 131 | if [ "$PROVIDER_NAME" = "tpm" ] || [ "$PROVIDER_NAME" = "all" ]; then 132 | echo Start and configure TPM server 133 | # Copy the NVChip for previously stored state. This is needed for the key mappings test. 134 | cp /tmp/ondisk/NVChip . 135 | # Start and configure TPM server 136 | tpm_server & 137 | TPM_SRV_PID=$! 138 | sleep 5 139 | # The -c flag is not used because some keys were created in the TPM via the generate-keys.sh 140 | # script. Ownership has already been taken with "tpm_pass". 141 | tpm2_startup -T mssim 142 | 143 | # Start and configure TPM server for MakeCredential 144 | TPM_MC_PORT=4321 145 | mkdir -p /tmp/mc_tpm 146 | pushd /tmp/mc_tpm 147 | tpm_server -port $TPM_MC_PORT & 148 | TPM_MC_SRV_PID=$! 149 | sleep 5 150 | tpm2_startup -c -T mssim:port=$TPM_MC_PORT 151 | popd 152 | fi 153 | 154 | if [ "$PROVIDER_NAME" = "pkcs11" ] || [ "$PROVIDER_NAME" = "all" ] || [ "$PROVIDER_NAME" = "coverage" ]; then 155 | pushd e2etest 156 | # This command suppose that the slot created by the container will be the first one that appears 157 | # when printing all the available slots. 158 | SLOT_NUMBER=$(softhsm2-util --show-slots | head -n2 | tail -n1 | cut -d " " -f 2) 159 | # shellcheck disable=SC2196 160 | SERIAL_NUMBER=$(softhsm2-util --show-slots | grep "Serial number:*" | head -n1 | egrep -ow "[0-9a-zA-Z]+" | tail -n1) 161 | # Find all TOML files in the directory (except Cargo.toml) and replace the commented slot number with the valid one 162 | find . -name "*toml" -not -name "Cargo.toml" -exec sed -i "s/^# slot_number.*$/slot_number = $SLOT_NUMBER/" {} \; 163 | find . -name "*toml" -not -name "Cargo.toml" -exec sed -i "s/^# serial_number.*$/serial_number = \"$SERIAL_NUMBER\"/" {} \; 164 | popd 165 | fi 166 | 167 | mkdir -p /run/parsec 168 | 169 | echo "Start Parsec for end-to-end tests" 170 | RUST_LOG=info RUST_BACKTRACE=1 /tmp/parsec/target/debug/parsec --config "$CONFIG_PATH" & 171 | 172 | # Sleep time needed to make sure Parsec is ready before launching the tests. 173 | sleep 5 174 | 175 | # Check that Parsec successfully started and is running 176 | pgrep -f /tmp/parsec/target/debug/parsec >/dev/null 177 | export PARSEC_SERVICE_ENDPOINT=unix:/run/parsec/parsec.sock 178 | pushd "${TESTDIR}" || exit 179 | go test -v --tags=end2endtest ./... 180 | popd || exit -------------------------------------------------------------------------------- /e2etest/signing_test.go: -------------------------------------------------------------------------------- 1 | // +build end2endtest 2 | 3 | // Copyright 2021 Contributors to the Parsec project. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | package e2etest 7 | 8 | import ( 9 | "testing" 10 | 11 | parsec "github.com/parallaxsecond/parsec-client-go/parsec" 12 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 13 | ) 14 | 15 | func TestSigning(t *testing.T) { 16 | 17 | f := initFixture(t) 18 | defer f.closeFixture(t) 19 | f.c.SetImplicitProvider(parsec.ProviderMBed) 20 | 21 | keyname := "sdfasd" 22 | message := "hello dolly" 23 | keyatts := parsec.DefaultKeyAttribute().SigningKey() 24 | keyalg := keyatts.KeyPolicy.KeyAlgorithm.GetAsymmetricSignature() 25 | if keyalg == nil { 26 | t.Fatal("Expected to be able to get AsymmetricSignatureAlgorithm back from keyatts, couldnt") 27 | } 28 | err := f.c.PsaGenerateKey(keyname, keyatts) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | f.deferredKeyDestroy(keyname) 33 | 34 | hash, err := f.c.PsaHashCompute([]byte(message), algorithm.HashAlgorithmTypeSHA256) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | 39 | signature, err := f.c.PsaSignHash(keyname, hash, keyalg) 40 | if err != nil { 41 | t.Fatal(err) 42 | } 43 | err = f.c.PsaVerifyHash(keyname, hash, signature, keyalg) 44 | if err != nil { 45 | t.Fatal(err) 46 | } 47 | 48 | // try verifying signature with hash of another message 49 | message = "hello world" 50 | hash, err = f.c.PsaHashCompute([]byte(message), algorithm.HashAlgorithmTypeSHA256) 51 | if err != nil { 52 | t.Fatal(err) 53 | } 54 | err = f.c.PsaVerifyHash(keyname, hash, signature, keyalg) 55 | if err == nil { 56 | t.Fatal(err) 57 | 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /e2etest/testclient_test.go: -------------------------------------------------------------------------------- 1 | // +build end2endtest 2 | 3 | // Copyright 2021 Contributors to the Parsec project. 4 | // SPDX-License-Identifier: Apache-2.0 5 | 6 | package e2etest 7 | 8 | import ( 9 | "testing" 10 | 11 | parsec "github.com/parallaxsecond/parsec-client-go/parsec" 12 | ) 13 | 14 | type testClient struct { 15 | c *parsec.BasicClient 16 | createdKeys []string 17 | } 18 | 19 | func initFixture(t *testing.T) *testClient { 20 | c, err := parsec.CreateConfiguredClient("ci-test-client") 21 | if err != nil { 22 | t.Fatal(err) 23 | return nil 24 | } 25 | c.SetImplicitProvider(parsec.ProviderPKCS11) 26 | return &testClient{c: c, createdKeys: make([]string, 0, 0)} 27 | } 28 | 29 | func (f *testClient) closeFixture(t *testing.T) { 30 | // Destroy any keys (may have gone anyway so ignore errors) 31 | for _, k := range f.createdKeys { 32 | _ = f.c.PsaDestroyKey(k) 33 | } 34 | err := f.c.Close() 35 | if err != nil { 36 | t.Fatal(err) 37 | return 38 | } 39 | 40 | } 41 | 42 | func (f *testClient) deferredKeyDestroy(keyName string) { 43 | f.createdKeys = append(f.createdKeys, keyName) 44 | } 45 | -------------------------------------------------------------------------------- /e2etest/unsupported_ops_test.go: -------------------------------------------------------------------------------- 1 | // +build e2etest 2 | 3 | // +build unsupportedfunctions 4 | 5 | // Copyright 2021 Contributors to the Parsec project. 6 | // SPDX-License-Identifier: Apache-2.0 7 | 8 | package e2etest 9 | 10 | // These tests are for functionality that should work according to interface spec but is not supported by any providers 11 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | module github.com/parallaxsecond/parsec-client-go 5 | 6 | go 1.15 7 | 8 | require ( 9 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect 10 | github.com/onsi/ginkgo v1.15.0 11 | github.com/onsi/gomega v1.10.5 12 | github.com/pkg/errors v0.9.1 13 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect 14 | google.golang.org/protobuf v1.23.0 15 | gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /interface/README.md: -------------------------------------------------------------------------------- 1 | # Interface 2 | This folder and subfolders contain the code to implement the protocol buffers interface to talk to the parsec daemon. 3 | 4 | This code is not part of the Parsec go language client public api and should not be used by client application developers directly. 5 | 6 | ## Sub Folders 7 | 8 | - [auth](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/auth) Authenticator code for authenticating with parsec daemon 9 | - [connection](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/connection) Manages the connection (currently only unix socket) between the client and the parsec daemon 10 | - [go-protobuf](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/go-protobuf) Intermediate protocol buffers definition files modified to add go packages - not stored in git. 11 | - [operations](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/operations) Generated code for marshaling and unmarshaling protocol buffers messages to communicate with parsec daemon. These files *are* stored in git so that end application developers do not need to install protocol buffers compilers. 12 | - [parsec-operations](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/parsec-operations) Git submodule containing protocol buffers definition of the parsec client interface. 13 | - [requests](https://github.com/parallaxsecond/parsec-client-go/tree/master/interface/requests) Basic client to interface with the parsec daemon. This client is functional but exposes protocol buffer specific extensions to data-types and so is not suitable for end application developers. 14 | 15 | -------------------------------------------------------------------------------- /interface/auth/auth_internal_suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package auth 5 | 6 | import ( 7 | "testing" 8 | 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | ) 12 | 13 | func TestAuth(t *testing.T) { 14 | RegisterFailHandler(Fail) 15 | RunSpecs(t, "auth package internal suite") 16 | } 17 | -------------------------------------------------------------------------------- /interface/auth/auth_internal_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package auth 5 | 6 | import ( 7 | "encoding/binary" 8 | "fmt" 9 | "os/user" 10 | "reflect" 11 | 12 | . "github.com/onsi/ginkgo" 13 | . "github.com/onsi/gomega" 14 | ) 15 | 16 | var _ = Describe("auth", func() { 17 | Describe("factory", func() { 18 | var authenticator Authenticator 19 | Context("Creating no auth authenticator", func() { 20 | BeforeEach(func() { 21 | authenticator = NewNoAuthAuthenticator() 22 | }) 23 | It("Should return *noAuthAuthenticator", func() { 24 | Expect(reflect.TypeOf(authenticator).String()).To(Equal("*auth.noAuthAuthenticator")) 25 | Expect(authenticator.GetType()).To(Equal(AuthNoAuth)) 26 | }) 27 | It("Should return an empty auth buffer", func() { 28 | tok, tokerr := authenticator.NewRequestAuth() 29 | Expect(tok).NotTo(BeNil()) 30 | Expect(tokerr).NotTo(HaveOccurred()) 31 | Expect(tok.AuthType()).To(Equal(AuthNoAuth)) 32 | buf := tok.Buffer().Bytes() 33 | Expect(len(buf)).To(Equal(0)) 34 | }) 35 | }) 36 | Context("Creating unix peer authenticator", func() { 37 | BeforeEach(func() { 38 | authenticator = NewUnixPeerAuthenticator() 39 | }) 40 | It("Should return *unixPeerAuthenticator", func() { 41 | Expect(reflect.TypeOf(authenticator).String()).To(Equal("*auth.unixPeerAuthenticator")) 42 | Expect(authenticator.GetType()).To(Equal(AuthUnixPeerCredentials)) 43 | }) 44 | It("Should return a 32 bit auth buffer", func() { 45 | tok, tokerr := authenticator.NewRequestAuth() 46 | Expect(tok).NotTo(BeNil()) 47 | Expect(tokerr).NotTo(HaveOccurred()) 48 | Expect(tok.AuthType()).To(Equal(AuthUnixPeerCredentials)) 49 | buf := tok.Buffer().Bytes() 50 | Expect(len(buf)).To(Equal(4)) 51 | currentUser, usererr := user.Current() 52 | Expect(usererr).NotTo(HaveOccurred()) 53 | var uid uint32 54 | usererr = binary.Read(tok.Buffer(), binary.LittleEndian, &uid) 55 | Expect(usererr).NotTo(HaveOccurred()) 56 | Expect(fmt.Sprint(uid)).To(Equal(currentUser.Uid)) 57 | }) 58 | }) 59 | Context("Creating AuthDirect authenticator", func() { 60 | const appName = "test app name" 61 | BeforeEach(func() { 62 | authenticator = NewDirectAuthenticator(appName) 63 | }) 64 | It("Should return *directAuthenticator", func() { 65 | Expect(reflect.TypeOf(authenticator).String()).To(Equal("*auth.directAuthenticator")) 66 | Expect(authenticator.GetType()).To(Equal(AuthDirect)) 67 | }) 68 | It("Should return bytes encoding app name", func() { 69 | tok, tokerr := authenticator.NewRequestAuth() 70 | Expect(tok).NotTo(BeNil()) 71 | Expect(tokerr).NotTo(HaveOccurred()) 72 | Expect(tok.AuthType()).To(Equal(AuthDirect)) 73 | buf := tok.Buffer().Bytes() 74 | Expect(string(buf)).To(Equal(appName)) 75 | }) 76 | }) 77 | }) 78 | Describe("Conversion from uint32", func() { 79 | Context("For valid types", func() { 80 | It("Should succeed", func() { 81 | for a := uint32(0); a <= uint32(AuthJwtSvid); a++ { 82 | authType, err := NewAuthenticationTypeFromU32(a) 83 | Expect(err).NotTo(HaveOccurred()) 84 | Expect(authType.IsValid()).To(BeTrue()) 85 | } 86 | }) 87 | }) 88 | Context("For invalid types", func() { 89 | It("Should fail", func() { 90 | for a := uint32(AuthJwtSvid) + 1; a <= uint32(255); a++ { 91 | authType, err := NewAuthenticationTypeFromU32(a) 92 | Expect(err).To(HaveOccurred()) 93 | Expect(authType).To(Equal(AuthenticationType(0))) // Returns default value 94 | } 95 | }) 96 | }) 97 | }) 98 | }) 99 | -------------------------------------------------------------------------------- /interface/auth/direct.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package auth 5 | 6 | import ( 7 | "bytes" 8 | ) 9 | 10 | type directAuthenticator struct { 11 | appName string 12 | } 13 | 14 | // NewDirectAuthenticator creates a new Direct authenticator that uses appName as the 15 | // means of authentication. 16 | func NewDirectAuthenticator(appName string) Authenticator { 17 | return &directAuthenticator{appName: appName} 18 | } 19 | 20 | // NewRequestAuth creates a new request authentication payload 21 | func (a *directAuthenticator) NewRequestAuth() (RequestAuthToken, error) { 22 | buf := &bytes.Buffer{} 23 | _, err := buf.WriteString(a.appName) 24 | if err != nil { 25 | return nil, err 26 | } 27 | r := &DefaultRequestAuthToken{buf: buf, authType: AuthDirect} 28 | return r, nil 29 | } 30 | 31 | // GetType get the type of the authenticator 32 | func (a *directAuthenticator) GetType() AuthenticationType { 33 | return AuthDirect 34 | } 35 | -------------------------------------------------------------------------------- /interface/auth/mod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package auth 5 | 6 | import ( 7 | "bytes" 8 | "fmt" 9 | ) 10 | 11 | // AuthenticationType identifies type of authentication to be used in a request message. 12 | type AuthenticationType uint8 13 | 14 | // Authentication Types 15 | const ( 16 | AuthNoAuth AuthenticationType = 0 17 | // Direct authentication 18 | AuthDirect AuthenticationType = 1 19 | // JSON Web Tokens (JWT) authentication (not currently supported) 20 | AuthJwt AuthenticationType = 2 21 | // Unix peer credentials authentication 22 | AuthUnixPeerCredentials AuthenticationType = 3 23 | // Authentication verifying a JWT SPIFFE Verifiable Identity Document 24 | AuthJwtSvid AuthenticationType = 4 25 | ) 26 | 27 | func (a AuthenticationType) IsValid() bool { 28 | return a <= AuthJwtSvid 29 | } 30 | 31 | func NewAuthenticationTypeFromU32(t uint32) (AuthenticationType, error) { 32 | if t > uint32(AuthJwtSvid) { 33 | return AuthNoAuth, fmt.Errorf("cannot convert value %v to AuthenticationType", t) 34 | } 35 | return AuthenticationType(t), nil 36 | } 37 | 38 | // Authenticator interface for an authenticator 39 | // GetType get the type of the authenticator 40 | // NewRequestAuth creates a RequestAuthToken ready to populate a request 41 | type Authenticator interface { 42 | GetType() AuthenticationType 43 | NewRequestAuth() (RequestAuthToken, error) 44 | } 45 | 46 | // RequestAuthToken describes interface for token to contain an authentication field in a request 47 | type RequestAuthToken interface { 48 | Buffer() *bytes.Buffer 49 | AuthType() AuthenticationType 50 | } 51 | 52 | // DefaultRequestAuthToken represents a request authentication payload 53 | type DefaultRequestAuthToken struct { 54 | buf *bytes.Buffer 55 | authType AuthenticationType 56 | } 57 | 58 | // Buffer returns byte buffer with the token to be sent in a request to the server 59 | func (a DefaultRequestAuthToken) Buffer() *bytes.Buffer { 60 | return a.buf 61 | } 62 | 63 | // AuthType returns the auth type value to put in a request header 64 | func (a DefaultRequestAuthToken) AuthType() AuthenticationType { 65 | return a.authType 66 | } 67 | -------------------------------------------------------------------------------- /interface/auth/no_auth.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package auth 5 | 6 | import ( 7 | "bytes" 8 | ) 9 | 10 | type noAuthAuthenticator struct { 11 | } 12 | 13 | // NewNoAuthAuthenticator create a new authenticator that provides no authentication. 14 | // Used for testing and for core operations such as list_providers and list_authenticators 15 | func NewNoAuthAuthenticator() Authenticator { 16 | return &noAuthAuthenticator{} 17 | } 18 | 19 | // NewRequestAuth creates a new request authentication payload 20 | func (a noAuthAuthenticator) NewRequestAuth() (RequestAuthToken, error) { 21 | r := &DefaultRequestAuthToken{buf: &bytes.Buffer{}, authType: AuthNoAuth} 22 | return r, nil 23 | } 24 | 25 | // GetType get the type of the authenticator 26 | func (a *noAuthAuthenticator) GetType() AuthenticationType { 27 | return AuthNoAuth 28 | } 29 | -------------------------------------------------------------------------------- /interface/auth/unix_peer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package auth 5 | 6 | import ( 7 | "bytes" 8 | "encoding/binary" 9 | "os/user" 10 | "strconv" 11 | ) 12 | 13 | type unixPeerAuthenticator struct { 14 | } 15 | 16 | // NewUnixPeerAuthenticator creates a new authenticator that uses current unix user id as 17 | // means of authentication. 18 | func NewUnixPeerAuthenticator() Authenticator { 19 | return &unixPeerAuthenticator{} 20 | } 21 | 22 | // NewRequestAuth creates a new request authentication payload 23 | func (a unixPeerAuthenticator) NewRequestAuth() (RequestAuthToken, error) { 24 | r := &DefaultRequestAuthToken{buf: &bytes.Buffer{}, authType: AuthUnixPeerCredentials} 25 | currentUser, err := user.Current() 26 | if err != nil { 27 | return nil, err 28 | } 29 | uid, err := strconv.ParseUint(currentUser.Uid, 10, 32) //nolint // base 10 and 32 bit number obvious from context 30 | if err != nil { 31 | return nil, err 32 | } 33 | if err != nil { 34 | return nil, err 35 | } 36 | err = binary.Write(r.buf, binary.LittleEndian, uint32(uid)) 37 | if err != nil { 38 | return nil, err 39 | } 40 | return r, nil 41 | } 42 | 43 | // GetType get the type of the authenticator 44 | func (a *unixPeerAuthenticator) GetType() AuthenticationType { 45 | return AuthUnixPeerCredentials 46 | } 47 | -------------------------------------------------------------------------------- /interface/connection/conn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package connection 5 | 6 | import ( 7 | "fmt" 8 | "io" 9 | "net" 10 | "net/url" 11 | "os" 12 | "strings" 13 | ) 14 | 15 | const defaultUnixSocketAddress = "unix:/run/parsec/parsec.sock" 16 | const parsecEndpointEnvironmentVariable = "PARSEC_SERVICE_ENDPOINT" 17 | 18 | // Connection represents a connection to the parsec service. 19 | type Connection interface { 20 | // Open should be called before use 21 | Open() error 22 | // Methods to read, write and close the connection 23 | io.ReadWriteCloser 24 | } 25 | 26 | // type to manage unix socket connection 27 | type unixConnection struct { 28 | rwc io.ReadWriteCloser 29 | path string 30 | } 31 | 32 | // Read data from unix socket - conn must have been opened or an error will be returned 33 | func (conn *unixConnection) Read(p []byte) (n int, err error) { 34 | if conn.rwc == nil { 35 | return 0, fmt.Errorf("reading closed connection") 36 | } 37 | return conn.rwc.Read(p) 38 | } 39 | 40 | // Write data to unix socket - conn must have been opened or an error will be returned 41 | func (conn *unixConnection) Write(p []byte) (n int, err error) { 42 | if conn.rwc == nil { 43 | return 0, fmt.Errorf("writing closed connection") 44 | } 45 | return conn.rwc.Write(p) 46 | } 47 | 48 | // Close the unix socket 49 | func (conn *unixConnection) Close() error { 50 | // We'll allow closing a closed connection 51 | if conn.rwc != nil { 52 | err := conn.rwc.Close() 53 | if err != nil { 54 | return err 55 | } 56 | } 57 | conn.rwc = nil 58 | return nil 59 | } 60 | 61 | // Opens the unix socket ready for read/write 62 | func (conn *unixConnection) Open() error { 63 | rwc, err := net.Dial("unix", conn.path) 64 | 65 | if err != nil { 66 | return err 67 | } 68 | conn.rwc = rwc 69 | return nil 70 | } 71 | 72 | // NewDefaultConnection opens the default connection to the parsec service. 73 | // This returns a Connection. If the PARSEC_SERVICE_ENDPOINT environment 74 | // variable is set, then this will be used to determine how to connect to the 75 | // parsec service. This must be a valid URL, and currently only urls of the form 76 | // unix:/path are supported. 77 | // if the PARSEC_SERVICE_ENDPOINT environment variable is not set, then the default of 78 | // unix:/run/parsec/parsec.sock will be used 79 | // Connection implementations are not guaranteed to be thread safe, so should not be used 80 | // across threads. 81 | func NewDefaultConnection() (Connection, error) { 82 | addressRawURL := os.Getenv(parsecEndpointEnvironmentVariable) 83 | if addressRawURL == "" { 84 | addressRawURL = defaultUnixSocketAddress 85 | } 86 | 87 | sockURL, err := url.Parse(addressRawURL) 88 | if err != nil { 89 | return nil, err 90 | } 91 | switch strings.ToLower(sockURL.Scheme) { 92 | case "unix": 93 | return &unixConnection{ 94 | path: sockURL.Path, 95 | }, nil 96 | default: 97 | return nil, fmt.Errorf("unsupported url scheme %v", sockURL.Scheme) 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /interface/connection/conn_internal_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package connection 5 | 6 | import ( 7 | "io" 8 | "io/ioutil" 9 | "net" 10 | "os" 11 | "testing" 12 | "time" 13 | 14 | . "github.com/onsi/ginkgo" 15 | . "github.com/onsi/gomega" 16 | ) 17 | 18 | var _ = Describe("Connection Tests", func() { 19 | Context("No environment variable", func() { 20 | BeforeEach(func() { 21 | os.Setenv("PARSEC_SERVICE_ENDPOINT", "") 22 | }) 23 | AfterEach(func() { 24 | os.Setenv("PARSEC_SERVICE_ENDPOINT", "") 25 | }) 26 | It("Should have default address", func() { 27 | c, err := NewDefaultConnection() 28 | Expect(err).NotTo(HaveOccurred()) 29 | Expect(c).NotTo(BeNil()) 30 | uc, ok := c.(*unixConnection) 31 | Expect(ok).To(BeTrue()) 32 | Expect(uc).NotTo(BeNil()) 33 | Expect(uc.path).To(Equal("/run/parsec/parsec.sock")) 34 | }) 35 | }) 36 | Context("Set environment variable", func() { 37 | var sockPath string 38 | 39 | BeforeEach(func() { 40 | file, err := ioutil.TempFile("/tmp", "socktest") 41 | Expect(err).NotTo(HaveOccurred()) 42 | sockPath = file.Name() 43 | os.Setenv("PARSEC_SERVICE_ENDPOINT", "unix:"+sockPath) 44 | err = os.RemoveAll(file.Name()) 45 | Expect(err).NotTo(HaveOccurred()) 46 | l, err := net.Listen("unix", file.Name()) 47 | Expect(err).NotTo(HaveOccurred()) 48 | go func() { 49 | defer l.Close() 50 | unixL, ok := l.(*net.UnixListener) 51 | Expect(ok).To(BeTrue()) 52 | err = unixL.SetDeadline(time.Now().Add(time.Second * 2)) 53 | Expect(err).NotTo(HaveOccurred()) 54 | conn, err := l.Accept() 55 | Expect(err).NotTo(HaveOccurred()) 56 | defer conn.Close() 57 | _, err = io.Copy(conn, conn) 58 | Expect(err).NotTo(HaveOccurred()) 59 | }() 60 | }) 61 | AfterEach(func() { 62 | os.Setenv("PARSEC_SERVICE_ENDPOINT", "") 63 | }) 64 | It("Should have the configured address and be usable", func() { 65 | c, err := NewDefaultConnection() 66 | Expect(err).NotTo(HaveOccurred()) 67 | Expect(c).NotTo(BeNil()) 68 | uc, ok := c.(*unixConnection) 69 | Expect(ok).To(BeTrue()) 70 | Expect(uc).NotTo(BeNil()) 71 | Expect(uc.path).To(Equal(sockPath)) 72 | 73 | err = uc.Open() 74 | Expect(err).NotTo(HaveOccurred()) 75 | n, err := uc.Write([]byte("hello")) 76 | Expect(err).NotTo(HaveOccurred()) 77 | Expect(n).To(Equal(5)) 78 | buf := make([]byte, 10) 79 | n, err = uc.Read(buf) 80 | Expect(err).NotTo(HaveOccurred()) 81 | Expect(n).To(Equal(5)) 82 | Expect(string(buf[:n])).To(Equal("hello")) 83 | err = uc.Close() 84 | Expect(err).NotTo(HaveOccurred()) 85 | }) 86 | It("Should not allow use before open", func() { 87 | c, err := NewDefaultConnection() 88 | Expect(err).NotTo(HaveOccurred()) 89 | Expect(c).NotTo(BeNil()) 90 | uc, ok := c.(*unixConnection) 91 | Expect(ok).To(BeTrue()) 92 | Expect(uc).NotTo(BeNil()) 93 | Expect(uc.path).To(Equal(sockPath)) 94 | 95 | buf := make([]byte, 10) 96 | 97 | _, err = uc.Write([]byte("hello")) 98 | Expect(err).To(HaveOccurred()) 99 | _, err = uc.Read(buf) 100 | Expect(err).To(HaveOccurred()) 101 | err = uc.Close() 102 | // We allow closed connections to be closed 103 | Expect(err).NotTo(HaveOccurred()) 104 | 105 | err = uc.Open() 106 | Expect(err).NotTo(HaveOccurred()) 107 | n, err := uc.Write([]byte("hello")) 108 | Expect(err).NotTo(HaveOccurred()) 109 | Expect(n).To(Equal(5)) 110 | n, err = uc.Read(buf) 111 | Expect(err).NotTo(HaveOccurred()) 112 | Expect(n).To(Equal(5)) 113 | Expect(string(buf[:n])).To(Equal("hello")) 114 | err = uc.Close() 115 | Expect(err).NotTo(HaveOccurred()) 116 | 117 | _, err = uc.Write([]byte("hello")) 118 | Expect(err).To(HaveOccurred()) 119 | _, err = uc.Read(buf) 120 | Expect(err).To(HaveOccurred()) 121 | err = uc.Close() 122 | Expect(err).NotTo(HaveOccurred()) 123 | 124 | }) 125 | 126 | }) 127 | Context("Invalid endpoint scheme", func() { 128 | BeforeEach(func() { 129 | os.Setenv("PARSEC_SERVICE_ENDPOINT", "http://google.com") 130 | }) 131 | AfterEach(func() { 132 | os.Setenv("PARSEC_SERVICE_ENDPOINT", "") 133 | }) 134 | It("Should fail on on create", func() { 135 | _, err := NewDefaultConnection() 136 | Expect(err).To(HaveOccurred()) 137 | }) 138 | 139 | }) 140 | }) 141 | 142 | func TestRequests(t *testing.T) { 143 | RegisterFailHandler(Fail) 144 | RunSpecs(t, "connection package external test suite") 145 | } 146 | -------------------------------------------------------------------------------- /interface/go-protobuf/.gitignore: -------------------------------------------------------------------------------- 1 | *.proto 2 | -------------------------------------------------------------------------------- /interface/operations/deleteclient/delete_client.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2021 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: delete_client.proto 10 | 11 | package deleteclient 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | Client string `protobuf:"bytes,1,opt,name=client,proto3" json:"client,omitempty"` 33 | } 34 | 35 | func (x *Operation) Reset() { 36 | *x = Operation{} 37 | if protoimpl.UnsafeEnabled { 38 | mi := &file_delete_client_proto_msgTypes[0] 39 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 40 | ms.StoreMessageInfo(mi) 41 | } 42 | } 43 | 44 | func (x *Operation) String() string { 45 | return protoimpl.X.MessageStringOf(x) 46 | } 47 | 48 | func (*Operation) ProtoMessage() {} 49 | 50 | func (x *Operation) ProtoReflect() protoreflect.Message { 51 | mi := &file_delete_client_proto_msgTypes[0] 52 | if protoimpl.UnsafeEnabled && x != nil { 53 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 54 | if ms.LoadMessageInfo() == nil { 55 | ms.StoreMessageInfo(mi) 56 | } 57 | return ms 58 | } 59 | return mi.MessageOf(x) 60 | } 61 | 62 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 63 | func (*Operation) Descriptor() ([]byte, []int) { 64 | return file_delete_client_proto_rawDescGZIP(), []int{0} 65 | } 66 | 67 | func (x *Operation) GetClient() string { 68 | if x != nil { 69 | return x.Client 70 | } 71 | return "" 72 | } 73 | 74 | type Result struct { 75 | state protoimpl.MessageState 76 | sizeCache protoimpl.SizeCache 77 | unknownFields protoimpl.UnknownFields 78 | } 79 | 80 | func (x *Result) Reset() { 81 | *x = Result{} 82 | if protoimpl.UnsafeEnabled { 83 | mi := &file_delete_client_proto_msgTypes[1] 84 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 85 | ms.StoreMessageInfo(mi) 86 | } 87 | } 88 | 89 | func (x *Result) String() string { 90 | return protoimpl.X.MessageStringOf(x) 91 | } 92 | 93 | func (*Result) ProtoMessage() {} 94 | 95 | func (x *Result) ProtoReflect() protoreflect.Message { 96 | mi := &file_delete_client_proto_msgTypes[1] 97 | if protoimpl.UnsafeEnabled && x != nil { 98 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 99 | if ms.LoadMessageInfo() == nil { 100 | ms.StoreMessageInfo(mi) 101 | } 102 | return ms 103 | } 104 | return mi.MessageOf(x) 105 | } 106 | 107 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 108 | func (*Result) Descriptor() ([]byte, []int) { 109 | return file_delete_client_proto_rawDescGZIP(), []int{1} 110 | } 111 | 112 | var File_delete_client_proto protoreflect.FileDescriptor 113 | 114 | var file_delete_client_proto_rawDesc = []byte{ 115 | 0x0a, 0x13, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 116 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x63, 0x6c, 117 | 0x69, 0x65, 0x6e, 0x74, 0x22, 0x23, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 118 | 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 119 | 0x09, 0x52, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x22, 0x08, 0x0a, 0x06, 0x52, 0x65, 0x73, 120 | 0x75, 0x6c, 0x74, 0x42, 0x4e, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 121 | 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x61, 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 122 | 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x63, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x67, 123 | 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 0x72, 124 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x63, 0x6c, 0x69, 125 | 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 126 | } 127 | 128 | var ( 129 | file_delete_client_proto_rawDescOnce sync.Once 130 | file_delete_client_proto_rawDescData = file_delete_client_proto_rawDesc 131 | ) 132 | 133 | func file_delete_client_proto_rawDescGZIP() []byte { 134 | file_delete_client_proto_rawDescOnce.Do(func() { 135 | file_delete_client_proto_rawDescData = protoimpl.X.CompressGZIP(file_delete_client_proto_rawDescData) 136 | }) 137 | return file_delete_client_proto_rawDescData 138 | } 139 | 140 | var file_delete_client_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 141 | var file_delete_client_proto_goTypes = []interface{}{ 142 | (*Operation)(nil), // 0: delete_client.Operation 143 | (*Result)(nil), // 1: delete_client.Result 144 | } 145 | var file_delete_client_proto_depIdxs = []int32{ 146 | 0, // [0:0] is the sub-list for method output_type 147 | 0, // [0:0] is the sub-list for method input_type 148 | 0, // [0:0] is the sub-list for extension type_name 149 | 0, // [0:0] is the sub-list for extension extendee 150 | 0, // [0:0] is the sub-list for field type_name 151 | } 152 | 153 | func init() { file_delete_client_proto_init() } 154 | func file_delete_client_proto_init() { 155 | if File_delete_client_proto != nil { 156 | return 157 | } 158 | if !protoimpl.UnsafeEnabled { 159 | file_delete_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 160 | switch v := v.(*Operation); i { 161 | case 0: 162 | return &v.state 163 | case 1: 164 | return &v.sizeCache 165 | case 2: 166 | return &v.unknownFields 167 | default: 168 | return nil 169 | } 170 | } 171 | file_delete_client_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 172 | switch v := v.(*Result); i { 173 | case 0: 174 | return &v.state 175 | case 1: 176 | return &v.sizeCache 177 | case 2: 178 | return &v.unknownFields 179 | default: 180 | return nil 181 | } 182 | } 183 | } 184 | type x struct{} 185 | out := protoimpl.TypeBuilder{ 186 | File: protoimpl.DescBuilder{ 187 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 188 | RawDescriptor: file_delete_client_proto_rawDesc, 189 | NumEnums: 0, 190 | NumMessages: 2, 191 | NumExtensions: 0, 192 | NumServices: 0, 193 | }, 194 | GoTypes: file_delete_client_proto_goTypes, 195 | DependencyIndexes: file_delete_client_proto_depIdxs, 196 | MessageInfos: file_delete_client_proto_msgTypes, 197 | }.Build() 198 | File_delete_client_proto = out.File 199 | file_delete_client_proto_rawDesc = nil 200 | file_delete_client_proto_goTypes = nil 201 | file_delete_client_proto_depIdxs = nil 202 | } 203 | -------------------------------------------------------------------------------- /interface/operations/listclients/list_clients.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2021 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: list_clients.proto 10 | 11 | package listclients 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | } 32 | 33 | func (x *Operation) Reset() { 34 | *x = Operation{} 35 | if protoimpl.UnsafeEnabled { 36 | mi := &file_list_clients_proto_msgTypes[0] 37 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 38 | ms.StoreMessageInfo(mi) 39 | } 40 | } 41 | 42 | func (x *Operation) String() string { 43 | return protoimpl.X.MessageStringOf(x) 44 | } 45 | 46 | func (*Operation) ProtoMessage() {} 47 | 48 | func (x *Operation) ProtoReflect() protoreflect.Message { 49 | mi := &file_list_clients_proto_msgTypes[0] 50 | if protoimpl.UnsafeEnabled && x != nil { 51 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 52 | if ms.LoadMessageInfo() == nil { 53 | ms.StoreMessageInfo(mi) 54 | } 55 | return ms 56 | } 57 | return mi.MessageOf(x) 58 | } 59 | 60 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 61 | func (*Operation) Descriptor() ([]byte, []int) { 62 | return file_list_clients_proto_rawDescGZIP(), []int{0} 63 | } 64 | 65 | type Result struct { 66 | state protoimpl.MessageState 67 | sizeCache protoimpl.SizeCache 68 | unknownFields protoimpl.UnknownFields 69 | 70 | Clients []string `protobuf:"bytes,1,rep,name=clients,proto3" json:"clients,omitempty"` 71 | } 72 | 73 | func (x *Result) Reset() { 74 | *x = Result{} 75 | if protoimpl.UnsafeEnabled { 76 | mi := &file_list_clients_proto_msgTypes[1] 77 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 78 | ms.StoreMessageInfo(mi) 79 | } 80 | } 81 | 82 | func (x *Result) String() string { 83 | return protoimpl.X.MessageStringOf(x) 84 | } 85 | 86 | func (*Result) ProtoMessage() {} 87 | 88 | func (x *Result) ProtoReflect() protoreflect.Message { 89 | mi := &file_list_clients_proto_msgTypes[1] 90 | if protoimpl.UnsafeEnabled && x != nil { 91 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 92 | if ms.LoadMessageInfo() == nil { 93 | ms.StoreMessageInfo(mi) 94 | } 95 | return ms 96 | } 97 | return mi.MessageOf(x) 98 | } 99 | 100 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 101 | func (*Result) Descriptor() ([]byte, []int) { 102 | return file_list_clients_proto_rawDescGZIP(), []int{1} 103 | } 104 | 105 | func (x *Result) GetClients() []string { 106 | if x != nil { 107 | return x.Clients 108 | } 109 | return nil 110 | } 111 | 112 | var File_list_clients_proto protoreflect.FileDescriptor 113 | 114 | var file_list_clients_proto_rawDesc = []byte{ 115 | 0x0a, 0x12, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 116 | 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 117 | 0x74, 0x73, 0x22, 0x0b, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 118 | 0x22, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x69, 119 | 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 120 | 0x6e, 0x74, 0x73, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 121 | 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x61, 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 122 | 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x63, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x67, 123 | 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 0x72, 124 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x63, 0x6c, 0x69, 0x65, 0x6e, 125 | 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 126 | } 127 | 128 | var ( 129 | file_list_clients_proto_rawDescOnce sync.Once 130 | file_list_clients_proto_rawDescData = file_list_clients_proto_rawDesc 131 | ) 132 | 133 | func file_list_clients_proto_rawDescGZIP() []byte { 134 | file_list_clients_proto_rawDescOnce.Do(func() { 135 | file_list_clients_proto_rawDescData = protoimpl.X.CompressGZIP(file_list_clients_proto_rawDescData) 136 | }) 137 | return file_list_clients_proto_rawDescData 138 | } 139 | 140 | var file_list_clients_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 141 | var file_list_clients_proto_goTypes = []interface{}{ 142 | (*Operation)(nil), // 0: list_clients.Operation 143 | (*Result)(nil), // 1: list_clients.Result 144 | } 145 | var file_list_clients_proto_depIdxs = []int32{ 146 | 0, // [0:0] is the sub-list for method output_type 147 | 0, // [0:0] is the sub-list for method input_type 148 | 0, // [0:0] is the sub-list for extension type_name 149 | 0, // [0:0] is the sub-list for extension extendee 150 | 0, // [0:0] is the sub-list for field type_name 151 | } 152 | 153 | func init() { file_list_clients_proto_init() } 154 | func file_list_clients_proto_init() { 155 | if File_list_clients_proto != nil { 156 | return 157 | } 158 | if !protoimpl.UnsafeEnabled { 159 | file_list_clients_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 160 | switch v := v.(*Operation); i { 161 | case 0: 162 | return &v.state 163 | case 1: 164 | return &v.sizeCache 165 | case 2: 166 | return &v.unknownFields 167 | default: 168 | return nil 169 | } 170 | } 171 | file_list_clients_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 172 | switch v := v.(*Result); i { 173 | case 0: 174 | return &v.state 175 | case 1: 176 | return &v.sizeCache 177 | case 2: 178 | return &v.unknownFields 179 | default: 180 | return nil 181 | } 182 | } 183 | } 184 | type x struct{} 185 | out := protoimpl.TypeBuilder{ 186 | File: protoimpl.DescBuilder{ 187 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 188 | RawDescriptor: file_list_clients_proto_rawDesc, 189 | NumEnums: 0, 190 | NumMessages: 2, 191 | NumExtensions: 0, 192 | NumServices: 0, 193 | }, 194 | GoTypes: file_list_clients_proto_goTypes, 195 | DependencyIndexes: file_list_clients_proto_depIdxs, 196 | MessageInfos: file_list_clients_proto_msgTypes, 197 | }.Build() 198 | File_list_clients_proto = out.File 199 | file_list_clients_proto_rawDesc = nil 200 | file_list_clients_proto_goTypes = nil 201 | file_list_clients_proto_depIdxs = nil 202 | } 203 | -------------------------------------------------------------------------------- /interface/operations/listopcodes/list_opcodes.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: list_opcodes.proto 10 | 11 | package listopcodes 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | ProviderId uint32 `protobuf:"varint,1,opt,name=provider_id,json=providerId,proto3" json:"provider_id,omitempty"` 33 | } 34 | 35 | func (x *Operation) Reset() { 36 | *x = Operation{} 37 | if protoimpl.UnsafeEnabled { 38 | mi := &file_list_opcodes_proto_msgTypes[0] 39 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 40 | ms.StoreMessageInfo(mi) 41 | } 42 | } 43 | 44 | func (x *Operation) String() string { 45 | return protoimpl.X.MessageStringOf(x) 46 | } 47 | 48 | func (*Operation) ProtoMessage() {} 49 | 50 | func (x *Operation) ProtoReflect() protoreflect.Message { 51 | mi := &file_list_opcodes_proto_msgTypes[0] 52 | if protoimpl.UnsafeEnabled && x != nil { 53 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 54 | if ms.LoadMessageInfo() == nil { 55 | ms.StoreMessageInfo(mi) 56 | } 57 | return ms 58 | } 59 | return mi.MessageOf(x) 60 | } 61 | 62 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 63 | func (*Operation) Descriptor() ([]byte, []int) { 64 | return file_list_opcodes_proto_rawDescGZIP(), []int{0} 65 | } 66 | 67 | func (x *Operation) GetProviderId() uint32 { 68 | if x != nil { 69 | return x.ProviderId 70 | } 71 | return 0 72 | } 73 | 74 | type Result struct { 75 | state protoimpl.MessageState 76 | sizeCache protoimpl.SizeCache 77 | unknownFields protoimpl.UnknownFields 78 | 79 | Opcodes []uint32 `protobuf:"varint,1,rep,packed,name=opcodes,proto3" json:"opcodes,omitempty"` 80 | } 81 | 82 | func (x *Result) Reset() { 83 | *x = Result{} 84 | if protoimpl.UnsafeEnabled { 85 | mi := &file_list_opcodes_proto_msgTypes[1] 86 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 87 | ms.StoreMessageInfo(mi) 88 | } 89 | } 90 | 91 | func (x *Result) String() string { 92 | return protoimpl.X.MessageStringOf(x) 93 | } 94 | 95 | func (*Result) ProtoMessage() {} 96 | 97 | func (x *Result) ProtoReflect() protoreflect.Message { 98 | mi := &file_list_opcodes_proto_msgTypes[1] 99 | if protoimpl.UnsafeEnabled && x != nil { 100 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 101 | if ms.LoadMessageInfo() == nil { 102 | ms.StoreMessageInfo(mi) 103 | } 104 | return ms 105 | } 106 | return mi.MessageOf(x) 107 | } 108 | 109 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 110 | func (*Result) Descriptor() ([]byte, []int) { 111 | return file_list_opcodes_proto_rawDescGZIP(), []int{1} 112 | } 113 | 114 | func (x *Result) GetOpcodes() []uint32 { 115 | if x != nil { 116 | return x.Opcodes 117 | } 118 | return nil 119 | } 120 | 121 | var File_list_opcodes_proto protoreflect.FileDescriptor 122 | 123 | var file_list_opcodes_proto_rawDesc = []byte{ 124 | 0x0a, 0x12, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x6f, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2e, 0x70, 125 | 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x6f, 0x70, 0x63, 0x6f, 0x64, 126 | 0x65, 0x73, 0x22, 0x2c, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 127 | 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 128 | 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 129 | 0x22, 0x22, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 130 | 0x63, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x07, 0x6f, 0x70, 0x63, 131 | 0x6f, 0x64, 0x65, 0x73, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 132 | 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x61, 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 133 | 0x64, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x63, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 134 | 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 135 | 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x63, 0x6f, 136 | 0x64, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 137 | } 138 | 139 | var ( 140 | file_list_opcodes_proto_rawDescOnce sync.Once 141 | file_list_opcodes_proto_rawDescData = file_list_opcodes_proto_rawDesc 142 | ) 143 | 144 | func file_list_opcodes_proto_rawDescGZIP() []byte { 145 | file_list_opcodes_proto_rawDescOnce.Do(func() { 146 | file_list_opcodes_proto_rawDescData = protoimpl.X.CompressGZIP(file_list_opcodes_proto_rawDescData) 147 | }) 148 | return file_list_opcodes_proto_rawDescData 149 | } 150 | 151 | var file_list_opcodes_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 152 | var file_list_opcodes_proto_goTypes = []interface{}{ 153 | (*Operation)(nil), // 0: list_opcodes.Operation 154 | (*Result)(nil), // 1: list_opcodes.Result 155 | } 156 | var file_list_opcodes_proto_depIdxs = []int32{ 157 | 0, // [0:0] is the sub-list for method output_type 158 | 0, // [0:0] is the sub-list for method input_type 159 | 0, // [0:0] is the sub-list for extension type_name 160 | 0, // [0:0] is the sub-list for extension extendee 161 | 0, // [0:0] is the sub-list for field type_name 162 | } 163 | 164 | func init() { file_list_opcodes_proto_init() } 165 | func file_list_opcodes_proto_init() { 166 | if File_list_opcodes_proto != nil { 167 | return 168 | } 169 | if !protoimpl.UnsafeEnabled { 170 | file_list_opcodes_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 171 | switch v := v.(*Operation); i { 172 | case 0: 173 | return &v.state 174 | case 1: 175 | return &v.sizeCache 176 | case 2: 177 | return &v.unknownFields 178 | default: 179 | return nil 180 | } 181 | } 182 | file_list_opcodes_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 183 | switch v := v.(*Result); i { 184 | case 0: 185 | return &v.state 186 | case 1: 187 | return &v.sizeCache 188 | case 2: 189 | return &v.unknownFields 190 | default: 191 | return nil 192 | } 193 | } 194 | } 195 | type x struct{} 196 | out := protoimpl.TypeBuilder{ 197 | File: protoimpl.DescBuilder{ 198 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 199 | RawDescriptor: file_list_opcodes_proto_rawDesc, 200 | NumEnums: 0, 201 | NumMessages: 2, 202 | NumExtensions: 0, 203 | NumServices: 0, 204 | }, 205 | GoTypes: file_list_opcodes_proto_goTypes, 206 | DependencyIndexes: file_list_opcodes_proto_depIdxs, 207 | MessageInfos: file_list_opcodes_proto_msgTypes, 208 | }.Build() 209 | File_list_opcodes_proto = out.File 210 | file_list_opcodes_proto_rawDesc = nil 211 | file_list_opcodes_proto_goTypes = nil 212 | file_list_opcodes_proto_depIdxs = nil 213 | } 214 | -------------------------------------------------------------------------------- /interface/operations/ping/ping.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: ping.proto 10 | 11 | package ping 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | } 32 | 33 | func (x *Operation) Reset() { 34 | *x = Operation{} 35 | if protoimpl.UnsafeEnabled { 36 | mi := &file_ping_proto_msgTypes[0] 37 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 38 | ms.StoreMessageInfo(mi) 39 | } 40 | } 41 | 42 | func (x *Operation) String() string { 43 | return protoimpl.X.MessageStringOf(x) 44 | } 45 | 46 | func (*Operation) ProtoMessage() {} 47 | 48 | func (x *Operation) ProtoReflect() protoreflect.Message { 49 | mi := &file_ping_proto_msgTypes[0] 50 | if protoimpl.UnsafeEnabled && x != nil { 51 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 52 | if ms.LoadMessageInfo() == nil { 53 | ms.StoreMessageInfo(mi) 54 | } 55 | return ms 56 | } 57 | return mi.MessageOf(x) 58 | } 59 | 60 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 61 | func (*Operation) Descriptor() ([]byte, []int) { 62 | return file_ping_proto_rawDescGZIP(), []int{0} 63 | } 64 | 65 | type Result struct { 66 | state protoimpl.MessageState 67 | sizeCache protoimpl.SizeCache 68 | unknownFields protoimpl.UnknownFields 69 | 70 | WireProtocolVersionMaj uint32 `protobuf:"varint,1,opt,name=wire_protocol_version_maj,json=wireProtocolVersionMaj,proto3" json:"wire_protocol_version_maj,omitempty"` // Cast down to 8 bits 71 | WireProtocolVersionMin uint32 `protobuf:"varint,2,opt,name=wire_protocol_version_min,json=wireProtocolVersionMin,proto3" json:"wire_protocol_version_min,omitempty"` // Cast down to 8 bits 72 | } 73 | 74 | func (x *Result) Reset() { 75 | *x = Result{} 76 | if protoimpl.UnsafeEnabled { 77 | mi := &file_ping_proto_msgTypes[1] 78 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 79 | ms.StoreMessageInfo(mi) 80 | } 81 | } 82 | 83 | func (x *Result) String() string { 84 | return protoimpl.X.MessageStringOf(x) 85 | } 86 | 87 | func (*Result) ProtoMessage() {} 88 | 89 | func (x *Result) ProtoReflect() protoreflect.Message { 90 | mi := &file_ping_proto_msgTypes[1] 91 | if protoimpl.UnsafeEnabled && x != nil { 92 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 93 | if ms.LoadMessageInfo() == nil { 94 | ms.StoreMessageInfo(mi) 95 | } 96 | return ms 97 | } 98 | return mi.MessageOf(x) 99 | } 100 | 101 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 102 | func (*Result) Descriptor() ([]byte, []int) { 103 | return file_ping_proto_rawDescGZIP(), []int{1} 104 | } 105 | 106 | func (x *Result) GetWireProtocolVersionMaj() uint32 { 107 | if x != nil { 108 | return x.WireProtocolVersionMaj 109 | } 110 | return 0 111 | } 112 | 113 | func (x *Result) GetWireProtocolVersionMin() uint32 { 114 | if x != nil { 115 | return x.WireProtocolVersionMin 116 | } 117 | return 0 118 | } 119 | 120 | var File_ping_proto protoreflect.FileDescriptor 121 | 122 | var file_ping_proto_rawDesc = []byte{ 123 | 0x0a, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x70, 0x69, 124 | 0x6e, 0x67, 0x22, 0x0b, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 125 | 0x7e, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x39, 0x0a, 0x19, 0x77, 0x69, 0x72, 126 | 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 127 | 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x77, 0x69, 128 | 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 129 | 0x6e, 0x4d, 0x61, 0x6a, 0x12, 0x39, 0x0a, 0x19, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x70, 0x72, 0x6f, 130 | 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 131 | 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x77, 0x69, 0x72, 0x65, 0x50, 0x72, 0x6f, 132 | 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x42, 133 | 0x46, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 134 | 0x72, 0x61, 0x6c, 0x6c, 0x61, 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x70, 0x61, 0x72, 135 | 0x73, 0x65, 0x63, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 136 | 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 137 | 0x6e, 0x73, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 138 | } 139 | 140 | var ( 141 | file_ping_proto_rawDescOnce sync.Once 142 | file_ping_proto_rawDescData = file_ping_proto_rawDesc 143 | ) 144 | 145 | func file_ping_proto_rawDescGZIP() []byte { 146 | file_ping_proto_rawDescOnce.Do(func() { 147 | file_ping_proto_rawDescData = protoimpl.X.CompressGZIP(file_ping_proto_rawDescData) 148 | }) 149 | return file_ping_proto_rawDescData 150 | } 151 | 152 | var file_ping_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 153 | var file_ping_proto_goTypes = []interface{}{ 154 | (*Operation)(nil), // 0: ping.Operation 155 | (*Result)(nil), // 1: ping.Result 156 | } 157 | var file_ping_proto_depIdxs = []int32{ 158 | 0, // [0:0] is the sub-list for method output_type 159 | 0, // [0:0] is the sub-list for method input_type 160 | 0, // [0:0] is the sub-list for extension type_name 161 | 0, // [0:0] is the sub-list for extension extendee 162 | 0, // [0:0] is the sub-list for field type_name 163 | } 164 | 165 | func init() { file_ping_proto_init() } 166 | func file_ping_proto_init() { 167 | if File_ping_proto != nil { 168 | return 169 | } 170 | if !protoimpl.UnsafeEnabled { 171 | file_ping_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 172 | switch v := v.(*Operation); i { 173 | case 0: 174 | return &v.state 175 | case 1: 176 | return &v.sizeCache 177 | case 2: 178 | return &v.unknownFields 179 | default: 180 | return nil 181 | } 182 | } 183 | file_ping_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 184 | switch v := v.(*Result); i { 185 | case 0: 186 | return &v.state 187 | case 1: 188 | return &v.sizeCache 189 | case 2: 190 | return &v.unknownFields 191 | default: 192 | return nil 193 | } 194 | } 195 | } 196 | type x struct{} 197 | out := protoimpl.TypeBuilder{ 198 | File: protoimpl.DescBuilder{ 199 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 200 | RawDescriptor: file_ping_proto_rawDesc, 201 | NumEnums: 0, 202 | NumMessages: 2, 203 | NumExtensions: 0, 204 | NumServices: 0, 205 | }, 206 | GoTypes: file_ping_proto_goTypes, 207 | DependencyIndexes: file_ping_proto_depIdxs, 208 | MessageInfos: file_ping_proto_msgTypes, 209 | }.Build() 210 | File_ping_proto = out.File 211 | file_ping_proto_rawDesc = nil 212 | file_ping_proto_goTypes = nil 213 | file_ping_proto_depIdxs = nil 214 | } 215 | -------------------------------------------------------------------------------- /interface/operations/psadestroykey/psa_destroy_key.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: psa_destroy_key.proto 10 | 11 | package psadestroykey 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` 33 | } 34 | 35 | func (x *Operation) Reset() { 36 | *x = Operation{} 37 | if protoimpl.UnsafeEnabled { 38 | mi := &file_psa_destroy_key_proto_msgTypes[0] 39 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 40 | ms.StoreMessageInfo(mi) 41 | } 42 | } 43 | 44 | func (x *Operation) String() string { 45 | return protoimpl.X.MessageStringOf(x) 46 | } 47 | 48 | func (*Operation) ProtoMessage() {} 49 | 50 | func (x *Operation) ProtoReflect() protoreflect.Message { 51 | mi := &file_psa_destroy_key_proto_msgTypes[0] 52 | if protoimpl.UnsafeEnabled && x != nil { 53 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 54 | if ms.LoadMessageInfo() == nil { 55 | ms.StoreMessageInfo(mi) 56 | } 57 | return ms 58 | } 59 | return mi.MessageOf(x) 60 | } 61 | 62 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 63 | func (*Operation) Descriptor() ([]byte, []int) { 64 | return file_psa_destroy_key_proto_rawDescGZIP(), []int{0} 65 | } 66 | 67 | func (x *Operation) GetKeyName() string { 68 | if x != nil { 69 | return x.KeyName 70 | } 71 | return "" 72 | } 73 | 74 | type Result struct { 75 | state protoimpl.MessageState 76 | sizeCache protoimpl.SizeCache 77 | unknownFields protoimpl.UnknownFields 78 | } 79 | 80 | func (x *Result) Reset() { 81 | *x = Result{} 82 | if protoimpl.UnsafeEnabled { 83 | mi := &file_psa_destroy_key_proto_msgTypes[1] 84 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 85 | ms.StoreMessageInfo(mi) 86 | } 87 | } 88 | 89 | func (x *Result) String() string { 90 | return protoimpl.X.MessageStringOf(x) 91 | } 92 | 93 | func (*Result) ProtoMessage() {} 94 | 95 | func (x *Result) ProtoReflect() protoreflect.Message { 96 | mi := &file_psa_destroy_key_proto_msgTypes[1] 97 | if protoimpl.UnsafeEnabled && x != nil { 98 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 99 | if ms.LoadMessageInfo() == nil { 100 | ms.StoreMessageInfo(mi) 101 | } 102 | return ms 103 | } 104 | return mi.MessageOf(x) 105 | } 106 | 107 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 108 | func (*Result) Descriptor() ([]byte, []int) { 109 | return file_psa_destroy_key_proto_rawDescGZIP(), []int{1} 110 | } 111 | 112 | var File_psa_destroy_key_proto protoreflect.FileDescriptor 113 | 114 | var file_psa_destroy_key_proto_rawDesc = []byte{ 115 | 0x0a, 0x15, 0x70, 0x73, 0x61, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x5f, 0x6b, 0x65, 116 | 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x73, 0x61, 0x5f, 0x64, 0x65, 0x73, 117 | 0x74, 0x72, 0x6f, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x26, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 118 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 119 | 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 120 | 0x22, 0x08, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x4f, 0x5a, 0x4d, 0x67, 0x69, 121 | 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x61, 122 | 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x63, 0x2d, 0x63, 123 | 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 124 | 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x70, 0x73, 125 | 0x61, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x6b, 0x65, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 126 | 0x74, 0x6f, 0x33, 127 | } 128 | 129 | var ( 130 | file_psa_destroy_key_proto_rawDescOnce sync.Once 131 | file_psa_destroy_key_proto_rawDescData = file_psa_destroy_key_proto_rawDesc 132 | ) 133 | 134 | func file_psa_destroy_key_proto_rawDescGZIP() []byte { 135 | file_psa_destroy_key_proto_rawDescOnce.Do(func() { 136 | file_psa_destroy_key_proto_rawDescData = protoimpl.X.CompressGZIP(file_psa_destroy_key_proto_rawDescData) 137 | }) 138 | return file_psa_destroy_key_proto_rawDescData 139 | } 140 | 141 | var file_psa_destroy_key_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 142 | var file_psa_destroy_key_proto_goTypes = []interface{}{ 143 | (*Operation)(nil), // 0: psa_destroy_key.Operation 144 | (*Result)(nil), // 1: psa_destroy_key.Result 145 | } 146 | var file_psa_destroy_key_proto_depIdxs = []int32{ 147 | 0, // [0:0] is the sub-list for method output_type 148 | 0, // [0:0] is the sub-list for method input_type 149 | 0, // [0:0] is the sub-list for extension type_name 150 | 0, // [0:0] is the sub-list for extension extendee 151 | 0, // [0:0] is the sub-list for field type_name 152 | } 153 | 154 | func init() { file_psa_destroy_key_proto_init() } 155 | func file_psa_destroy_key_proto_init() { 156 | if File_psa_destroy_key_proto != nil { 157 | return 158 | } 159 | if !protoimpl.UnsafeEnabled { 160 | file_psa_destroy_key_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 161 | switch v := v.(*Operation); i { 162 | case 0: 163 | return &v.state 164 | case 1: 165 | return &v.sizeCache 166 | case 2: 167 | return &v.unknownFields 168 | default: 169 | return nil 170 | } 171 | } 172 | file_psa_destroy_key_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 173 | switch v := v.(*Result); i { 174 | case 0: 175 | return &v.state 176 | case 1: 177 | return &v.sizeCache 178 | case 2: 179 | return &v.unknownFields 180 | default: 181 | return nil 182 | } 183 | } 184 | } 185 | type x struct{} 186 | out := protoimpl.TypeBuilder{ 187 | File: protoimpl.DescBuilder{ 188 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 189 | RawDescriptor: file_psa_destroy_key_proto_rawDesc, 190 | NumEnums: 0, 191 | NumMessages: 2, 192 | NumExtensions: 0, 193 | NumServices: 0, 194 | }, 195 | GoTypes: file_psa_destroy_key_proto_goTypes, 196 | DependencyIndexes: file_psa_destroy_key_proto_depIdxs, 197 | MessageInfos: file_psa_destroy_key_proto_msgTypes, 198 | }.Build() 199 | File_psa_destroy_key_proto = out.File 200 | file_psa_destroy_key_proto_rawDesc = nil 201 | file_psa_destroy_key_proto_goTypes = nil 202 | file_psa_destroy_key_proto_depIdxs = nil 203 | } 204 | -------------------------------------------------------------------------------- /interface/operations/psaexportkey/psa_export_key.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: psa_export_key.proto 10 | 11 | package psaexportkey 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` 33 | } 34 | 35 | func (x *Operation) Reset() { 36 | *x = Operation{} 37 | if protoimpl.UnsafeEnabled { 38 | mi := &file_psa_export_key_proto_msgTypes[0] 39 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 40 | ms.StoreMessageInfo(mi) 41 | } 42 | } 43 | 44 | func (x *Operation) String() string { 45 | return protoimpl.X.MessageStringOf(x) 46 | } 47 | 48 | func (*Operation) ProtoMessage() {} 49 | 50 | func (x *Operation) ProtoReflect() protoreflect.Message { 51 | mi := &file_psa_export_key_proto_msgTypes[0] 52 | if protoimpl.UnsafeEnabled && x != nil { 53 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 54 | if ms.LoadMessageInfo() == nil { 55 | ms.StoreMessageInfo(mi) 56 | } 57 | return ms 58 | } 59 | return mi.MessageOf(x) 60 | } 61 | 62 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 63 | func (*Operation) Descriptor() ([]byte, []int) { 64 | return file_psa_export_key_proto_rawDescGZIP(), []int{0} 65 | } 66 | 67 | func (x *Operation) GetKeyName() string { 68 | if x != nil { 69 | return x.KeyName 70 | } 71 | return "" 72 | } 73 | 74 | type Result struct { 75 | state protoimpl.MessageState 76 | sizeCache protoimpl.SizeCache 77 | unknownFields protoimpl.UnknownFields 78 | 79 | Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` 80 | } 81 | 82 | func (x *Result) Reset() { 83 | *x = Result{} 84 | if protoimpl.UnsafeEnabled { 85 | mi := &file_psa_export_key_proto_msgTypes[1] 86 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 87 | ms.StoreMessageInfo(mi) 88 | } 89 | } 90 | 91 | func (x *Result) String() string { 92 | return protoimpl.X.MessageStringOf(x) 93 | } 94 | 95 | func (*Result) ProtoMessage() {} 96 | 97 | func (x *Result) ProtoReflect() protoreflect.Message { 98 | mi := &file_psa_export_key_proto_msgTypes[1] 99 | if protoimpl.UnsafeEnabled && x != nil { 100 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 101 | if ms.LoadMessageInfo() == nil { 102 | ms.StoreMessageInfo(mi) 103 | } 104 | return ms 105 | } 106 | return mi.MessageOf(x) 107 | } 108 | 109 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 110 | func (*Result) Descriptor() ([]byte, []int) { 111 | return file_psa_export_key_proto_rawDescGZIP(), []int{1} 112 | } 113 | 114 | func (x *Result) GetData() []byte { 115 | if x != nil { 116 | return x.Data 117 | } 118 | return nil 119 | } 120 | 121 | var File_psa_export_key_proto protoreflect.FileDescriptor 122 | 123 | var file_psa_export_key_proto_rawDesc = []byte{ 124 | 0x0a, 0x14, 0x70, 0x73, 0x61, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6b, 0x65, 0x79, 125 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x70, 0x73, 0x61, 0x5f, 0x65, 0x78, 0x70, 0x6f, 126 | 0x72, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x26, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 127 | 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 128 | 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x1c, 129 | 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 130 | 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x4e, 0x5a, 0x4c, 131 | 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6c, 132 | 0x6c, 0x61, 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x63, 133 | 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 134 | 0x66, 0x61, 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 135 | 0x70, 0x73, 0x61, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x6b, 0x65, 0x79, 0x62, 0x06, 0x70, 0x72, 136 | 0x6f, 0x74, 0x6f, 0x33, 137 | } 138 | 139 | var ( 140 | file_psa_export_key_proto_rawDescOnce sync.Once 141 | file_psa_export_key_proto_rawDescData = file_psa_export_key_proto_rawDesc 142 | ) 143 | 144 | func file_psa_export_key_proto_rawDescGZIP() []byte { 145 | file_psa_export_key_proto_rawDescOnce.Do(func() { 146 | file_psa_export_key_proto_rawDescData = protoimpl.X.CompressGZIP(file_psa_export_key_proto_rawDescData) 147 | }) 148 | return file_psa_export_key_proto_rawDescData 149 | } 150 | 151 | var file_psa_export_key_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 152 | var file_psa_export_key_proto_goTypes = []interface{}{ 153 | (*Operation)(nil), // 0: psa_export_key.Operation 154 | (*Result)(nil), // 1: psa_export_key.Result 155 | } 156 | var file_psa_export_key_proto_depIdxs = []int32{ 157 | 0, // [0:0] is the sub-list for method output_type 158 | 0, // [0:0] is the sub-list for method input_type 159 | 0, // [0:0] is the sub-list for extension type_name 160 | 0, // [0:0] is the sub-list for extension extendee 161 | 0, // [0:0] is the sub-list for field type_name 162 | } 163 | 164 | func init() { file_psa_export_key_proto_init() } 165 | func file_psa_export_key_proto_init() { 166 | if File_psa_export_key_proto != nil { 167 | return 168 | } 169 | if !protoimpl.UnsafeEnabled { 170 | file_psa_export_key_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 171 | switch v := v.(*Operation); i { 172 | case 0: 173 | return &v.state 174 | case 1: 175 | return &v.sizeCache 176 | case 2: 177 | return &v.unknownFields 178 | default: 179 | return nil 180 | } 181 | } 182 | file_psa_export_key_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 183 | switch v := v.(*Result); i { 184 | case 0: 185 | return &v.state 186 | case 1: 187 | return &v.sizeCache 188 | case 2: 189 | return &v.unknownFields 190 | default: 191 | return nil 192 | } 193 | } 194 | } 195 | type x struct{} 196 | out := protoimpl.TypeBuilder{ 197 | File: protoimpl.DescBuilder{ 198 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 199 | RawDescriptor: file_psa_export_key_proto_rawDesc, 200 | NumEnums: 0, 201 | NumMessages: 2, 202 | NumExtensions: 0, 203 | NumServices: 0, 204 | }, 205 | GoTypes: file_psa_export_key_proto_goTypes, 206 | DependencyIndexes: file_psa_export_key_proto_depIdxs, 207 | MessageInfos: file_psa_export_key_proto_msgTypes, 208 | }.Build() 209 | File_psa_export_key_proto = out.File 210 | file_psa_export_key_proto_rawDesc = nil 211 | file_psa_export_key_proto_goTypes = nil 212 | file_psa_export_key_proto_depIdxs = nil 213 | } 214 | -------------------------------------------------------------------------------- /interface/operations/psaexportpublickey/psa_export_public_key.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: psa_export_public_key.proto 10 | 11 | package psaexportpublickey 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` 33 | } 34 | 35 | func (x *Operation) Reset() { 36 | *x = Operation{} 37 | if protoimpl.UnsafeEnabled { 38 | mi := &file_psa_export_public_key_proto_msgTypes[0] 39 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 40 | ms.StoreMessageInfo(mi) 41 | } 42 | } 43 | 44 | func (x *Operation) String() string { 45 | return protoimpl.X.MessageStringOf(x) 46 | } 47 | 48 | func (*Operation) ProtoMessage() {} 49 | 50 | func (x *Operation) ProtoReflect() protoreflect.Message { 51 | mi := &file_psa_export_public_key_proto_msgTypes[0] 52 | if protoimpl.UnsafeEnabled && x != nil { 53 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 54 | if ms.LoadMessageInfo() == nil { 55 | ms.StoreMessageInfo(mi) 56 | } 57 | return ms 58 | } 59 | return mi.MessageOf(x) 60 | } 61 | 62 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 63 | func (*Operation) Descriptor() ([]byte, []int) { 64 | return file_psa_export_public_key_proto_rawDescGZIP(), []int{0} 65 | } 66 | 67 | func (x *Operation) GetKeyName() string { 68 | if x != nil { 69 | return x.KeyName 70 | } 71 | return "" 72 | } 73 | 74 | type Result struct { 75 | state protoimpl.MessageState 76 | sizeCache protoimpl.SizeCache 77 | unknownFields protoimpl.UnknownFields 78 | 79 | Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` 80 | } 81 | 82 | func (x *Result) Reset() { 83 | *x = Result{} 84 | if protoimpl.UnsafeEnabled { 85 | mi := &file_psa_export_public_key_proto_msgTypes[1] 86 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 87 | ms.StoreMessageInfo(mi) 88 | } 89 | } 90 | 91 | func (x *Result) String() string { 92 | return protoimpl.X.MessageStringOf(x) 93 | } 94 | 95 | func (*Result) ProtoMessage() {} 96 | 97 | func (x *Result) ProtoReflect() protoreflect.Message { 98 | mi := &file_psa_export_public_key_proto_msgTypes[1] 99 | if protoimpl.UnsafeEnabled && x != nil { 100 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 101 | if ms.LoadMessageInfo() == nil { 102 | ms.StoreMessageInfo(mi) 103 | } 104 | return ms 105 | } 106 | return mi.MessageOf(x) 107 | } 108 | 109 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 110 | func (*Result) Descriptor() ([]byte, []int) { 111 | return file_psa_export_public_key_proto_rawDescGZIP(), []int{1} 112 | } 113 | 114 | func (x *Result) GetData() []byte { 115 | if x != nil { 116 | return x.Data 117 | } 118 | return nil 119 | } 120 | 121 | var File_psa_export_public_key_proto protoreflect.FileDescriptor 122 | 123 | var file_psa_export_public_key_proto_rawDesc = []byte{ 124 | 0x0a, 0x1b, 0x70, 0x73, 0x61, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 125 | 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x70, 126 | 0x73, 0x61, 0x5f, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 127 | 0x5f, 0x6b, 0x65, 0x79, 0x22, 0x26, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 128 | 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 129 | 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x1c, 0x0a, 0x06, 130 | 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 131 | 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x54, 0x5a, 0x52, 0x67, 0x69, 132 | 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x61, 133 | 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x63, 0x2d, 0x63, 134 | 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 135 | 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x70, 0x73, 136 | 0x61, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 137 | 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 138 | } 139 | 140 | var ( 141 | file_psa_export_public_key_proto_rawDescOnce sync.Once 142 | file_psa_export_public_key_proto_rawDescData = file_psa_export_public_key_proto_rawDesc 143 | ) 144 | 145 | func file_psa_export_public_key_proto_rawDescGZIP() []byte { 146 | file_psa_export_public_key_proto_rawDescOnce.Do(func() { 147 | file_psa_export_public_key_proto_rawDescData = protoimpl.X.CompressGZIP(file_psa_export_public_key_proto_rawDescData) 148 | }) 149 | return file_psa_export_public_key_proto_rawDescData 150 | } 151 | 152 | var file_psa_export_public_key_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 153 | var file_psa_export_public_key_proto_goTypes = []interface{}{ 154 | (*Operation)(nil), // 0: psa_export_public_key.Operation 155 | (*Result)(nil), // 1: psa_export_public_key.Result 156 | } 157 | var file_psa_export_public_key_proto_depIdxs = []int32{ 158 | 0, // [0:0] is the sub-list for method output_type 159 | 0, // [0:0] is the sub-list for method input_type 160 | 0, // [0:0] is the sub-list for extension type_name 161 | 0, // [0:0] is the sub-list for extension extendee 162 | 0, // [0:0] is the sub-list for field type_name 163 | } 164 | 165 | func init() { file_psa_export_public_key_proto_init() } 166 | func file_psa_export_public_key_proto_init() { 167 | if File_psa_export_public_key_proto != nil { 168 | return 169 | } 170 | if !protoimpl.UnsafeEnabled { 171 | file_psa_export_public_key_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 172 | switch v := v.(*Operation); i { 173 | case 0: 174 | return &v.state 175 | case 1: 176 | return &v.sizeCache 177 | case 2: 178 | return &v.unknownFields 179 | default: 180 | return nil 181 | } 182 | } 183 | file_psa_export_public_key_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 184 | switch v := v.(*Result); i { 185 | case 0: 186 | return &v.state 187 | case 1: 188 | return &v.sizeCache 189 | case 2: 190 | return &v.unknownFields 191 | default: 192 | return nil 193 | } 194 | } 195 | } 196 | type x struct{} 197 | out := protoimpl.TypeBuilder{ 198 | File: protoimpl.DescBuilder{ 199 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 200 | RawDescriptor: file_psa_export_public_key_proto_rawDesc, 201 | NumEnums: 0, 202 | NumMessages: 2, 203 | NumExtensions: 0, 204 | NumServices: 0, 205 | }, 206 | GoTypes: file_psa_export_public_key_proto_goTypes, 207 | DependencyIndexes: file_psa_export_public_key_proto_depIdxs, 208 | MessageInfos: file_psa_export_public_key_proto_msgTypes, 209 | }.Build() 210 | File_psa_export_public_key_proto = out.File 211 | file_psa_export_public_key_proto_rawDesc = nil 212 | file_psa_export_public_key_proto_goTypes = nil 213 | file_psa_export_public_key_proto_depIdxs = nil 214 | } 215 | -------------------------------------------------------------------------------- /interface/operations/psageneraterandom/psa_generate_random.pb.go: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2020 Contributors to the Parsec project. 3 | // SPDX-License-Identifier: Apache-2.0 4 | 5 | // Code generated by protoc-gen-go. DO NOT EDIT. 6 | // versions: 7 | // protoc-gen-go v1.26.0 8 | // protoc v3.6.1 9 | // source: psa_generate_random.proto 10 | 11 | package psageneraterandom 12 | 13 | import ( 14 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 15 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 16 | reflect "reflect" 17 | sync "sync" 18 | ) 19 | 20 | const ( 21 | // Verify that this generated code is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 23 | // Verify that runtime/protoimpl is sufficiently up-to-date. 24 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 25 | ) 26 | 27 | type Operation struct { 28 | state protoimpl.MessageState 29 | sizeCache protoimpl.SizeCache 30 | unknownFields protoimpl.UnknownFields 31 | 32 | Size uint64 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"` 33 | } 34 | 35 | func (x *Operation) Reset() { 36 | *x = Operation{} 37 | if protoimpl.UnsafeEnabled { 38 | mi := &file_psa_generate_random_proto_msgTypes[0] 39 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 40 | ms.StoreMessageInfo(mi) 41 | } 42 | } 43 | 44 | func (x *Operation) String() string { 45 | return protoimpl.X.MessageStringOf(x) 46 | } 47 | 48 | func (*Operation) ProtoMessage() {} 49 | 50 | func (x *Operation) ProtoReflect() protoreflect.Message { 51 | mi := &file_psa_generate_random_proto_msgTypes[0] 52 | if protoimpl.UnsafeEnabled && x != nil { 53 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 54 | if ms.LoadMessageInfo() == nil { 55 | ms.StoreMessageInfo(mi) 56 | } 57 | return ms 58 | } 59 | return mi.MessageOf(x) 60 | } 61 | 62 | // Deprecated: Use Operation.ProtoReflect.Descriptor instead. 63 | func (*Operation) Descriptor() ([]byte, []int) { 64 | return file_psa_generate_random_proto_rawDescGZIP(), []int{0} 65 | } 66 | 67 | func (x *Operation) GetSize() uint64 { 68 | if x != nil { 69 | return x.Size 70 | } 71 | return 0 72 | } 73 | 74 | type Result struct { 75 | state protoimpl.MessageState 76 | sizeCache protoimpl.SizeCache 77 | unknownFields protoimpl.UnknownFields 78 | 79 | RandomBytes []byte `protobuf:"bytes,1,opt,name=random_bytes,json=randomBytes,proto3" json:"random_bytes,omitempty"` 80 | } 81 | 82 | func (x *Result) Reset() { 83 | *x = Result{} 84 | if protoimpl.UnsafeEnabled { 85 | mi := &file_psa_generate_random_proto_msgTypes[1] 86 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 87 | ms.StoreMessageInfo(mi) 88 | } 89 | } 90 | 91 | func (x *Result) String() string { 92 | return protoimpl.X.MessageStringOf(x) 93 | } 94 | 95 | func (*Result) ProtoMessage() {} 96 | 97 | func (x *Result) ProtoReflect() protoreflect.Message { 98 | mi := &file_psa_generate_random_proto_msgTypes[1] 99 | if protoimpl.UnsafeEnabled && x != nil { 100 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 101 | if ms.LoadMessageInfo() == nil { 102 | ms.StoreMessageInfo(mi) 103 | } 104 | return ms 105 | } 106 | return mi.MessageOf(x) 107 | } 108 | 109 | // Deprecated: Use Result.ProtoReflect.Descriptor instead. 110 | func (*Result) Descriptor() ([]byte, []int) { 111 | return file_psa_generate_random_proto_rawDescGZIP(), []int{1} 112 | } 113 | 114 | func (x *Result) GetRandomBytes() []byte { 115 | if x != nil { 116 | return x.RandomBytes 117 | } 118 | return nil 119 | } 120 | 121 | var File_psa_generate_random_proto protoreflect.FileDescriptor 122 | 123 | var file_psa_generate_random_proto_rawDesc = []byte{ 124 | 0x0a, 0x19, 0x70, 0x73, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x72, 125 | 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x70, 0x73, 0x61, 126 | 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 127 | 0x22, 0x1f, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 128 | 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 129 | 0x65, 0x22, 0x2b, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x72, 130 | 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 131 | 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x53, 132 | 0x5a, 0x51, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x61, 0x72, 133 | 0x61, 0x6c, 0x6c, 0x61, 0x78, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2f, 0x70, 0x61, 0x72, 0x73, 134 | 0x65, 0x63, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x67, 0x6f, 0x2f, 0x69, 0x6e, 0x74, 135 | 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 136 | 0x73, 0x2f, 0x70, 0x73, 0x61, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6e, 137 | 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 138 | } 139 | 140 | var ( 141 | file_psa_generate_random_proto_rawDescOnce sync.Once 142 | file_psa_generate_random_proto_rawDescData = file_psa_generate_random_proto_rawDesc 143 | ) 144 | 145 | func file_psa_generate_random_proto_rawDescGZIP() []byte { 146 | file_psa_generate_random_proto_rawDescOnce.Do(func() { 147 | file_psa_generate_random_proto_rawDescData = protoimpl.X.CompressGZIP(file_psa_generate_random_proto_rawDescData) 148 | }) 149 | return file_psa_generate_random_proto_rawDescData 150 | } 151 | 152 | var file_psa_generate_random_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 153 | var file_psa_generate_random_proto_goTypes = []interface{}{ 154 | (*Operation)(nil), // 0: psa_generate_random.Operation 155 | (*Result)(nil), // 1: psa_generate_random.Result 156 | } 157 | var file_psa_generate_random_proto_depIdxs = []int32{ 158 | 0, // [0:0] is the sub-list for method output_type 159 | 0, // [0:0] is the sub-list for method input_type 160 | 0, // [0:0] is the sub-list for extension type_name 161 | 0, // [0:0] is the sub-list for extension extendee 162 | 0, // [0:0] is the sub-list for field type_name 163 | } 164 | 165 | func init() { file_psa_generate_random_proto_init() } 166 | func file_psa_generate_random_proto_init() { 167 | if File_psa_generate_random_proto != nil { 168 | return 169 | } 170 | if !protoimpl.UnsafeEnabled { 171 | file_psa_generate_random_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 172 | switch v := v.(*Operation); i { 173 | case 0: 174 | return &v.state 175 | case 1: 176 | return &v.sizeCache 177 | case 2: 178 | return &v.unknownFields 179 | default: 180 | return nil 181 | } 182 | } 183 | file_psa_generate_random_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 184 | switch v := v.(*Result); i { 185 | case 0: 186 | return &v.state 187 | case 1: 188 | return &v.sizeCache 189 | case 2: 190 | return &v.unknownFields 191 | default: 192 | return nil 193 | } 194 | } 195 | } 196 | type x struct{} 197 | out := protoimpl.TypeBuilder{ 198 | File: protoimpl.DescBuilder{ 199 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 200 | RawDescriptor: file_psa_generate_random_proto_rawDesc, 201 | NumEnums: 0, 202 | NumMessages: 2, 203 | NumExtensions: 0, 204 | NumServices: 0, 205 | }, 206 | GoTypes: file_psa_generate_random_proto_goTypes, 207 | DependencyIndexes: file_psa_generate_random_proto_depIdxs, 208 | MessageInfos: file_psa_generate_random_proto_msgTypes, 209 | }.Build() 210 | File_psa_generate_random_proto = out.File 211 | file_psa_generate_random_proto_rawDesc = nil 212 | file_psa_generate_random_proto_goTypes = nil 213 | file_psa_generate_random_proto_depIdxs = nil 214 | } 215 | -------------------------------------------------------------------------------- /interface/requests/mod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests 5 | 6 | // OpCode type for parsec operations 7 | type OpCode uint32 8 | 9 | // Operation Codes 10 | const ( 11 | OpPing OpCode = 0x0001 12 | OpPsaGenerateKey OpCode = 0x0002 13 | OpPsaDestroyKey OpCode = 0x0003 14 | OpPsaSignHash OpCode = 0x0004 15 | OpPsaVerifyHash OpCode = 0x0005 16 | OpPsaImportKey OpCode = 0x0006 17 | OpPsaExportPublicKey OpCode = 0x0007 18 | OpListProviders OpCode = 0x0008 19 | OpListOpcodes OpCode = 0x0009 20 | OpPsaAsymmetricEncrypt OpCode = 0x000A 21 | OpPsaAsymmetricDecrypt OpCode = 0x000B 22 | OpPsaExportKey OpCode = 0x000C 23 | OpPsaGenerateRandom OpCode = 0x000D 24 | OpListAuthenticators OpCode = 0x000E 25 | OpPsaHashCompute OpCode = 0x000F 26 | OpPsaHashCompare OpCode = 0x0010 27 | OpPsaAeadEncrypt OpCode = 0x0011 28 | OpPsaAeadDecrypt OpCode = 0x0012 29 | OpPsaRawKeyAgreement OpCode = 0x0013 30 | OpPsaCipherEncrypt OpCode = 0x0014 31 | OpPsaCipherDecrypt OpCode = 0x0015 32 | OpPsaMacCompute OpCode = 0x0016 33 | OpPsaMacVerify OpCode = 0x0017 34 | OpPsaSignMessage OpCode = 0x0018 35 | OpPsaVerifyMessage OpCode = 0x0019 36 | OpListKeys OpCode = 0x001A 37 | OpListClients OpCode = 0x001B 38 | OpDeleteClient OpCode = 0x001C 39 | ) 40 | 41 | func (o OpCode) IsValid() bool { 42 | return o <= OpDeleteClient 43 | } 44 | -------------------------------------------------------------------------------- /interface/requests/provider.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests 5 | 6 | // ProviderID for providers 7 | type ProviderID uint8 8 | 9 | // Provider UUIDs 10 | const ( 11 | ProviderCore ProviderID = 0 12 | ProviderMBed ProviderID = 1 13 | ProviderPKCS11 ProviderID = 2 14 | ProviderTPM ProviderID = 3 15 | ProviderTrustedService ProviderID = 4 16 | ) 17 | 18 | // HasCrypto returns true if the provider supports crypto 19 | func (p ProviderID) HasCrypto() bool { 20 | return p.IsValid() && p != ProviderCore 21 | } 22 | 23 | func (p ProviderID) IsValid() bool { 24 | return p >= ProviderCore && p <= ProviderTrustedService 25 | } 26 | 27 | func (p ProviderID) String() string { 28 | switch p { 29 | case ProviderCore: 30 | return "Core" 31 | case ProviderMBed: 32 | return "MBed" 33 | case ProviderPKCS11: 34 | return "PKCS11" 35 | case ProviderTPM: 36 | return "TPM" 37 | case ProviderTrustedService: 38 | return "TrustedService" 39 | default: 40 | return "Unknown" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /interface/requests/request.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests 5 | 6 | import ( 7 | "bytes" 8 | 9 | "github.com/parallaxsecond/parsec-client-go/interface/auth" 10 | "google.golang.org/protobuf/proto" 11 | ) 12 | 13 | const requestHeaderSize uint16 = 30 14 | 15 | // RequestBody represents a marshaled request body 16 | type RequestBody struct { 17 | *bytes.Buffer 18 | } 19 | 20 | // Request represents a Parsec request 21 | type Request struct { 22 | Header wireHeader 23 | Body RequestBody 24 | Auth auth.RequestAuthToken 25 | } 26 | 27 | // NewRequest creates a new request based on the opcode and the message. 28 | func NewRequest(op OpCode, bdy proto.Message, authenticator auth.Authenticator, provider ProviderID) (*Request, error) { 29 | bodyBuf, err := proto.Marshal(bdy) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | authtok, err := authenticator.NewRequestAuth() 35 | if err != nil { 36 | return nil, err 37 | } 38 | r := &Request{ 39 | Header: wireHeader{ 40 | versionMajor: versionMajorOne, 41 | versionMinor: versionMinorZero, 42 | flags: flagsZero, 43 | provider: provider, 44 | // todo set session handles 45 | contentType: contentTypeProtobuf, 46 | authType: authtok.AuthType(), 47 | bodyLen: uint32(len(bodyBuf)), 48 | authLen: uint16(authtok.Buffer().Len()), 49 | opCode: op, 50 | Status: StatusSuccess, 51 | }, 52 | Body: RequestBody{ 53 | bytes.NewBuffer(bodyBuf), 54 | }, 55 | Auth: authtok, 56 | } 57 | return r, nil 58 | } 59 | 60 | // Pack encodes a request to the wire format 61 | func (r *Request) Pack() (*bytes.Buffer, error) { 62 | if err := r.Header.checkForRequest(); err != nil { 63 | return nil, err 64 | } 65 | b := bytes.NewBuffer([]byte{}) 66 | err := r.Header.pack(b) 67 | if err != nil { 68 | return nil, err 69 | } 70 | _, err = b.Write(r.Body.Bytes()) 71 | if err != nil { 72 | return nil, err 73 | } 74 | _, err = b.Write(r.Auth.Buffer().Bytes()) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return b, nil 79 | } 80 | -------------------------------------------------------------------------------- /interface/requests/requests_internal_suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests 5 | 6 | import ( 7 | "testing" 8 | 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | ) 12 | 13 | func TestRequests(t *testing.T) { 14 | RegisterFailHandler(Fail) 15 | RunSpecs(t, "requests package internal suite") 16 | } 17 | -------------------------------------------------------------------------------- /interface/requests/test/provider_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests_test 5 | 6 | import ( 7 | . "github.com/onsi/ginkgo" 8 | . "github.com/onsi/gomega" 9 | "github.com/parallaxsecond/parsec-client-go/interface/requests" 10 | ) 11 | 12 | var _ = Describe("Provider", func() { 13 | It("Should give correct values", func() { 14 | for i := 0; i < 255; i++ { 15 | p := requests.ProviderID(i) 16 | if p >= requests.ProviderCore && p <= requests.ProviderTrustedService { 17 | Expect(p.IsValid()).To(BeTrue()) 18 | Expect(p.String()).NotTo(Equal("Unknown")) 19 | } else { 20 | Expect(p.IsValid()).To(BeFalse()) 21 | Expect(p.String()).To(Equal("Unknown")) 22 | } 23 | if p == requests.ProviderCore { 24 | Expect(p.HasCrypto()).To(BeFalse()) 25 | } else if p.IsValid() { 26 | Expect(p.HasCrypto()).To(BeTrue()) 27 | } else { 28 | Expect(p.HasCrypto()).To(BeFalse()) 29 | 30 | } 31 | } 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /interface/requests/test/request_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests_test 5 | 6 | import ( 7 | "bytes" 8 | "fmt" 9 | 10 | . "github.com/onsi/ginkgo" 11 | . "github.com/onsi/gomega" 12 | "github.com/parallaxsecond/parsec-client-go/interface/auth" 13 | "github.com/parallaxsecond/parsec-client-go/interface/operations/ping" 14 | "github.com/parallaxsecond/parsec-client-go/interface/requests" 15 | ) 16 | 17 | type failingAuthenticator struct { 18 | returnTok bool 19 | } 20 | 21 | func (a *failingAuthenticator) GetType() auth.AuthenticationType { 22 | return auth.AuthDirect 23 | } 24 | func (a *failingAuthenticator) NewRequestAuth() (auth.RequestAuthToken, error) { 25 | if a.returnTok { 26 | return nilBufRequestAuthToken{}, nil 27 | } 28 | return nilBufRequestAuthToken{}, fmt.Errorf("deliberate error") 29 | } 30 | 31 | type nilBufRequestAuthToken struct{} 32 | 33 | func (t nilBufRequestAuthToken) Buffer() *bytes.Buffer { 34 | return nil 35 | } 36 | func (t nilBufRequestAuthToken) AuthType() auth.AuthenticationType { 37 | return auth.AuthNoAuth 38 | } 39 | 40 | var expectedPingReq = []byte{ 41 | 0x10, 0xa7, 0xc0, 0x5e, 0x1e, 0x00, 0x01, 0x00, 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00} 46 | 47 | // var expectedSignReq = []byte{ 48 | // 0x10, 0xa7, 0xc0, 0x5e, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | // 0x0a, 0x08, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x10, 0x01, 0x1a, 0x28, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x73, 0x67, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55} 50 | 51 | var _ = Describe("request", func() { 52 | Describe("ping", func() { 53 | var ( 54 | authenticator auth.Authenticator 55 | err, errpack error 56 | req *requests.Request 57 | packBuf *bytes.Buffer 58 | ) 59 | BeforeEach(func() { 60 | authenticator = auth.NewNoAuthAuthenticator() 61 | }) 62 | JustBeforeEach(func() { 63 | p := &ping.Result{} 64 | req, err = requests.NewRequest(requests.OpPing, p, authenticator, requests.ProviderCore) 65 | if err == nil && req != nil { 66 | packBuf, errpack = req.Pack() 67 | } 68 | 69 | }) 70 | Context("Parameters all correct", func() { 71 | It("should not error", func() { 72 | Expect(err).NotTo(HaveOccurred()) 73 | }) 74 | It("Should not return nil request", func() { 75 | Expect(req).NotTo(BeNil()) 76 | }) 77 | It("Should not give a pack error", func() { 78 | Expect(errpack).NotTo(HaveOccurred()) 79 | }) 80 | It("Should give a non nil buffer", func() { 81 | Expect(packBuf).NotTo(BeNil()) 82 | }) 83 | It("Should have buffer with expected contents", func() { 84 | Expect(packBuf.Bytes()).To(Equal([]byte(expectedPingReq))) //nolint:unconvert // required cast to ensure slice not array 85 | }) 86 | 87 | }) 88 | Context("Authenticator returns error instead of token", func() { 89 | BeforeEach(func() { 90 | authenticator = &failingAuthenticator{returnTok: false} 91 | }) 92 | It("should error", func() { 93 | Expect(err).To(HaveOccurred()) 94 | }) 95 | }) 96 | Context("Authenticator returns token with nil buffer", func() { 97 | It("should panic", func() { 98 | Expect(func() { 99 | authenticator = &failingAuthenticator{returnTok: true} 100 | p := &ping.Result{} 101 | _, _ = requests.NewRequest(requests.OpPing, p, authenticator, requests.ProviderCore) 102 | }).To(Panic()) 103 | }) 104 | }) 105 | }) 106 | }) 107 | -------------------------------------------------------------------------------- /interface/requests/test/requests_suite_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests_test 5 | 6 | import ( 7 | "testing" 8 | 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | ) 12 | 13 | func TestRequests(t *testing.T) { 14 | RegisterFailHandler(Fail) 15 | RunSpecs(t, "requests package internal suite") 16 | } 17 | -------------------------------------------------------------------------------- /interface/requests/test/response_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests_test 5 | 6 | import ( 7 | "bytes" 8 | 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | 12 | // "github.com/parallaxsecond/parsec-client-go/interface/operations/asym_sign" 13 | "github.com/parallaxsecond/parsec-client-go/interface/operations/ping" 14 | "github.com/parallaxsecond/parsec-client-go/interface/requests" 15 | ) 16 | 17 | var expectedPingResp = []byte{ 18 | 0x10, 0xa7, 0xc0, 0x5e, // magic 19 | 0x1e, 0x00, // header size 20 | 0x01, 0x00, // verMaj(8), verMin(8) 21 | 0x00, 0x00, // flags(16) 22 | 0x00, // provider 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // session(64) 24 | 0x00, // content type 25 | 0x00, // accept type 26 | 0x00, // auth type 27 | 0x02, 0x00, 0x00, 0x00, // bodylen(32) 28 | 0x00, 0x00, // auth len 29 | 0x01, 0x00, 0x00, 0x00, // opcode(32) 30 | 0x00, 0x00, // status 31 | 0x00, 0x00, // reserved 32 | 0x08, 0x01} // body(16) 33 | 34 | var mangledPingRespLong = []byte{ 35 | 0x10, 0xa7, 0xc0, 0x5e, // magic 36 | 0x1e, 0x00, // header size 37 | 0x01, 0x00, // verMaj(8), verMin(8) 38 | 0x00, 0x00, // flags(16) 39 | 0x00, // provider 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // session(64) 41 | 0x00, // content type 42 | 0x00, // accept type 43 | 0x00, // auth type 44 | 0x08, 0x00, 0x00, 0x00, // bodylen(32) 45 | 0x00, 0x00, // auth len 46 | 0x01, 0x00, 0x00, 0x00, // opcode(32) 47 | 0x00, 0x00, // status 48 | 0x00, 0x00, // reserved 49 | 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} // body(16) 50 | 51 | var mangledPingRespTrunc = []byte{ 52 | 0x10, 0xa7, 0xc0, 0x5e, // magic 53 | 0x1e, 0x00, // header size 54 | 0x01, 0x00, // verMaj(8), verMin(8) 55 | 0x00, 0x00, // flags(16) 56 | 0x00, // provider 57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // session(64) 58 | 0x00, // content type 59 | 0x00, // accept type 60 | 0x00, // auth type 61 | 0x01, 0x00, 0x00, 0x00, // bodylen(32) 62 | 0x00, 0x00, // auth len 63 | 0x01, 0x00, 0x00, 0x00, // opcode(32) 64 | 0x00, 0x00, // status 65 | 0x00, 0x00, // reserved 66 | 0x08} // body(16) 67 | 68 | // var expectedSignResp = []byte{ 69 | // 0x10, 0xa7, 0xc0, 0x5e, 0x1e, 0x00, 0x00, 0x00, // magic(32), hdrsize(16), verMaj(8), verMin(8) 70 | // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // flags(16), provider(8), session(64 (5/8)) 71 | // 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, // session(3/8), contenttype(8), accepttype(8), authtype(8), bodylen(32) (2/4) 72 | // 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0, 0x00, // bodylen(2/4), authlen(16) opcode(32) 73 | // 0x00, 0x00, 0x00, 0x0a, 0x04, 0x01, 0x02, 0x03, 0x04} 74 | // var expectedSignature = []byte{0x01, 0x02, 0x03, 0x04} 75 | 76 | var _ = Describe("response", func() { 77 | 78 | Describe("ping", func() { 79 | var ( 80 | res *ping.Result 81 | err error 82 | // response *requests.Response 83 | testbuf *bytes.Buffer 84 | expectedOpCode requests.OpCode 85 | ) 86 | BeforeEach(func() { 87 | res = &ping.Result{} 88 | testbuf = bytes.NewBuffer(expectedPingResp) 89 | expectedOpCode = requests.OpPing 90 | }) 91 | JustBeforeEach(func() { 92 | err = requests.ParseResponse(expectedOpCode, testbuf, res) 93 | 94 | }) 95 | Context("good parameters", func() { 96 | It("should not error", func() { 97 | Expect(err).NotTo(HaveOccurred()) 98 | }) 99 | It("should have correct version number", func() { 100 | Expect(res.GetWireProtocolVersionMaj()).To(Equal(uint32(1))) 101 | Expect(res.GetWireProtocolVersionMin()).To(Equal(uint32(0))) 102 | }) 103 | }) 104 | Context("nil result", func() { 105 | BeforeEach(func() { 106 | res = nil 107 | }) 108 | It("Should error", func() { 109 | Expect(err).To(HaveOccurred()) 110 | }) 111 | }) 112 | Context("nil buffer", func() { 113 | BeforeEach(func() { 114 | res = &ping.Result{} 115 | testbuf = nil 116 | }) 117 | It("Should error", func() { 118 | Expect(err).To(HaveOccurred()) 119 | }) 120 | }) 121 | Context("empty buffer", func() { 122 | BeforeEach(func() { 123 | res = &ping.Result{} 124 | testbuf = bytes.NewBuffer([]byte{}) 125 | }) 126 | It("Should error", func() { 127 | Expect(err).To(HaveOccurred()) 128 | }) 129 | }) 130 | Context("zeroed buffer", func() { 131 | BeforeEach(func() { 132 | buf := make([]byte, 36) 133 | for i := 0; i < len(buf); i++ { //nolint:gocritic 134 | buf[i] = 0x00 135 | } 136 | res = &ping.Result{} 137 | testbuf = bytes.NewBuffer(buf) 138 | }) 139 | It("Should error", func() { 140 | Expect(err).To(HaveOccurred()) 141 | }) 142 | }) 143 | Context("Short payload buffer", func() { 144 | BeforeEach(func() { 145 | buf := make([]byte, len(expectedPingResp)-1) 146 | copy(buf, expectedPingResp) 147 | res = &ping.Result{} 148 | 149 | testbuf = bytes.NewBuffer(buf) 150 | }) 151 | It("Should error", func() { 152 | Expect(err).To(HaveOccurred()) 153 | }) 154 | }) 155 | Context("Empty payload buffer", func() { 156 | BeforeEach(func() { 157 | buf := make([]byte, requests.WireHeaderSize) 158 | copy(buf, expectedPingResp) 159 | res = &ping.Result{} 160 | 161 | testbuf = bytes.NewBuffer(buf) 162 | }) 163 | It("Should error", func() { 164 | Expect(err).To(HaveOccurred()) 165 | }) 166 | }) 167 | Context("Incorrect op code", func() { 168 | BeforeEach(func() { 169 | expectedOpCode = requests.OpPsaAeadDecrypt 170 | }) 171 | It("Should error", func() { 172 | Expect(err).To(HaveOccurred()) 173 | }) 174 | }) 175 | Context("Mangled response buffer long", func() { 176 | BeforeEach(func() { 177 | testbuf = bytes.NewBuffer(mangledPingRespLong) 178 | }) 179 | It("Should error", func() { 180 | Expect(err).To(HaveOccurred()) 181 | }) 182 | }) 183 | Context("Mangled response buffer truncated", func() { 184 | BeforeEach(func() { 185 | testbuf = bytes.NewBuffer(mangledPingRespTrunc) 186 | }) 187 | It("Should error", func() { 188 | Expect(err).To(HaveOccurred()) 189 | }) 190 | }) 191 | }) 192 | 193 | Describe("Response Codes", func() { 194 | It("Should return correct values", func() { 195 | for i := 0; i < 10000; i++ { 196 | c := requests.StatusCode(i) 197 | valid := c.IsValid() 198 | err := c.ToErr() 199 | if c == requests.StatusSuccess { 200 | Expect(valid).To(BeTrue()) 201 | Expect(err).NotTo(HaveOccurred()) 202 | } else if (i > 0 && i <= 21) || (i >= 1132 && i <= 1152) { 203 | Expect(valid).To(BeTrue()) 204 | Expect(err).To(HaveOccurred()) 205 | } else { 206 | Expect(valid).To(BeFalse()) 207 | Expect(err).To(HaveOccurred()) 208 | } 209 | } 210 | }) 211 | }) 212 | 213 | }) 214 | -------------------------------------------------------------------------------- /interface/requests/wireheader.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package requests 5 | 6 | import ( 7 | "bytes" 8 | "encoding/binary" 9 | "fmt" 10 | 11 | "github.com/parallaxsecond/parsec-client-go/interface/auth" 12 | ) 13 | 14 | type contentType uint8 15 | type versionMajorType uint8 16 | type versionMinorType uint8 17 | type flagsType uint16 18 | type sessionType uint64 19 | type acceptType uint8 20 | 21 | const ( 22 | versionMajorOne versionMajorType = 0x01 23 | versionMinorZero versionMinorType = 0x00 24 | 25 | flagsZero flagsType = 0x0000 26 | ) 27 | 28 | func (f flagsType) isValid() bool { 29 | return f == flagsZero 30 | } 31 | 32 | func (a acceptType) isValid() bool { 33 | return a == acceptType(0x00) //nolint:gomnd // Only to be set on sent headers 34 | } 35 | 36 | const ( 37 | contentTypeProtobuf contentType = 0x00 38 | ) 39 | 40 | func (c contentType) isValid() bool { 41 | return c == contentTypeProtobuf 42 | } 43 | 44 | // magic number to indicate we have a wire header 45 | const magicNumber uint32 = 0x5EC0A710 46 | 47 | // wireHeader represents a request header 48 | type wireHeader struct { 49 | magicNumber uint32 50 | hdrSize uint16 51 | versionMajor versionMajorType 52 | versionMinor versionMinorType 53 | flags flagsType 54 | provider ProviderID 55 | session sessionType 56 | contentType contentType 57 | acceptType acceptType 58 | authType auth.AuthenticationType 59 | bodyLen uint32 60 | authLen uint16 61 | opCode OpCode 62 | Status StatusCode 63 | reserved1 uint8 64 | reserved2 uint8 65 | } 66 | 67 | func (r *wireHeader) pack(buf *bytes.Buffer) error { 68 | // panic rather than error as this is internal api and this shouldn't happen 69 | if buf == nil { 70 | panic("buffer pointer is nil") 71 | } 72 | 73 | // Check values are correct before packing 74 | 75 | r.magicNumber = magicNumber 76 | r.hdrSize = requestHeaderSize 77 | 78 | if err := r.checkForRequest(); err != nil { 79 | return err 80 | } 81 | 82 | err := binary.Write(buf, binary.LittleEndian, r) 83 | return err 84 | } 85 | 86 | func (r *wireHeader) checkForRequest() error { 87 | if !isSupportedWireHeaderVersion(r.versionMajor, r.versionMinor) { 88 | return fmt.Errorf("invalid version %v.%v", r.versionMajor, r.versionMinor) 89 | } 90 | if !r.flags.isValid() { 91 | return fmt.Errorf("invalid flags %v", r.flags) 92 | } 93 | if !r.contentType.isValid() { 94 | return fmt.Errorf("invalid content type %v", r.contentType) 95 | } 96 | if !r.acceptType.isValid() { 97 | return fmt.Errorf("invalid accept type %v", r.acceptType) 98 | } 99 | if !r.authType.IsValid() { 100 | return fmt.Errorf("invaliid auth type %v", r.authType) 101 | } 102 | return nil 103 | } 104 | 105 | func isSupportedWireHeaderVersion(maj versionMajorType, min versionMinorType) bool { 106 | return maj == versionMajorOne && min == versionMinorZero 107 | } 108 | 109 | const ( 110 | buffBytes8Bit int = 1 111 | buffBytes16Bit int = 2 112 | buffBytes32Bit int = 4 113 | buffBytes64Bit int = 8 114 | ) 115 | 116 | func parseWireHeaderFromBuf(buf *bytes.Buffer) (*wireHeader, error) { 117 | r := &wireHeader{} 118 | // panic rather than error as this is internal api and this shouldn't happen 119 | if buf == nil { 120 | panic("buffer pointer is nil") 121 | } 122 | r.magicNumber = binary.LittleEndian.Uint32(buf.Next(buffBytes32Bit)) 123 | if r.magicNumber != magicNumber { 124 | return nil, fmt.Errorf("invalid magic number") 125 | } 126 | r.hdrSize = binary.LittleEndian.Uint16(buf.Next(buffBytes16Bit)) 127 | if r.hdrSize != wireHeaderSizeValue { 128 | return nil, fmt.Errorf("invalid header size (%d != %d)", r.hdrSize, wireHeaderSizeValue) 129 | } 130 | r.versionMajor = versionMajorType(buf.Next(buffBytes8Bit)[0]) 131 | r.versionMinor = versionMinorType(buf.Next(buffBytes8Bit)[0]) 132 | if !isSupportedWireHeaderVersion(r.versionMajor, r.versionMinor) { 133 | return nil, fmt.Errorf("unsupported version number %v.%v", r.versionMajor, r.versionMinor) 134 | } 135 | r.flags = flagsType(binary.LittleEndian.Uint16(buf.Next(buffBytes16Bit))) 136 | if !r.flags.isValid() { 137 | return nil, fmt.Errorf("unsupported flags value %v", r.flags) 138 | } 139 | r.provider = ProviderID(buf.Next(buffBytes8Bit)[0]) 140 | if !r.provider.IsValid() { 141 | return nil, fmt.Errorf("invalid provider %v", r.provider) 142 | } 143 | r.session = sessionType(binary.LittleEndian.Uint64(buf.Next(buffBytes64Bit))) // Can take any value in range 144 | r.contentType = contentType(buf.Next(buffBytes8Bit)[0]) 145 | if !r.contentType.isValid() { 146 | return nil, fmt.Errorf("invalid content type %v", r.contentType) 147 | } 148 | r.acceptType = acceptType(buf.Next(buffBytes8Bit)[0]) // This should only be set in requests so we must not check value 149 | r.authType = auth.AuthenticationType(buf.Next(buffBytes8Bit)[0]) 150 | if !r.authType.IsValid() { 151 | return nil, fmt.Errorf("invalid auth type %v", r.authType) 152 | } 153 | r.bodyLen = binary.LittleEndian.Uint32(buf.Next(buffBytes32Bit)) 154 | r.authLen = binary.LittleEndian.Uint16(buf.Next(buffBytes16Bit)) 155 | r.opCode = OpCode(binary.LittleEndian.Uint32(buf.Next(buffBytes32Bit))) 156 | if !r.opCode.IsValid() { 157 | return nil, fmt.Errorf("invalid opcode %v", r.opCode) 158 | } 159 | r.Status = StatusCode(binary.LittleEndian.Uint16(buf.Next(buffBytes16Bit))) 160 | if !r.Status.IsValid() { 161 | return nil, fmt.Errorf("invalid response status code %v", r.Status) 162 | } 163 | r.reserved1 = buf.Next(buffBytes8Bit)[0] 164 | r.reserved2 = buf.Next(buffBytes8Bit)[0] 165 | if r.reserved1 != 0x00 || r.reserved2 != 0x00 { 166 | return nil, fmt.Errorf("reserved bytes must be zero") 167 | } 168 | 169 | return r, nil 170 | } 171 | -------------------------------------------------------------------------------- /mod.go: -------------------------------------------------------------------------------- 1 | package parseclientgo 2 | 3 | // Empty top level package allows parsec main client to be in parsec folder to allow for friendly name of parsec for client code. 4 | // This file required so package is valid and makefile build does not fail. 5 | -------------------------------------------------------------------------------- /parsec-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parallaxsecond/parsec-client-go/f0a77d263cf9e72dfc207551daa30f9ea07fda37/parsec-logo.png -------------------------------------------------------------------------------- /parsec/algorithm/aead.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 11 | ) 12 | 13 | type AeadFactory interface { 14 | Aead(algType AeadAlgorithmType) *Algorithm 15 | AeadShortenedTag(algType AeadAlgorithmType, tagLength uint32) *Algorithm 16 | } 17 | 18 | type aeadFactory struct{} 19 | 20 | func NewAead() AeadFactory { 21 | return &aeadFactory{} 22 | } 23 | func (a *aeadFactory) Aead(algType AeadAlgorithmType) *Algorithm { 24 | return &Algorithm{ 25 | variant: &AeadAlgorithm{ 26 | variant: &AeadAlgorithmDefaultLengthTag{ 27 | AeadAlg: algType, 28 | }, 29 | }, 30 | } 31 | } 32 | 33 | func (a *aeadFactory) AeadShortenedTag(algType AeadAlgorithmType, tagLength uint32) *Algorithm { 34 | return &Algorithm{ 35 | variant: &AeadAlgorithm{ 36 | variant: &AeadAlgorithmShortenedTag{ 37 | AeadAlg: algType, 38 | }, 39 | }, 40 | } 41 | } 42 | 43 | type AeadAlgorithmType uint32 44 | 45 | const ( 46 | AeadAlgorithmNODEFAULTTAG AeadAlgorithmType = 0 47 | AeadAlgorithmCCM AeadAlgorithmType = 1 48 | AeadAlgorithmGCM AeadAlgorithmType = 2 49 | AeadAlgorithmChacha20Poly1305 AeadAlgorithmType = 4 50 | ) 51 | 52 | type AeadAlgorithm struct { 53 | // *AeadWithDefaultLengthTag 54 | // *AeadWithShortenedTag 55 | variant aeadAlgorithmVariant 56 | } 57 | 58 | type aeadAlgorithmVariant interface { 59 | toWire 60 | isAeadAlgorithmVariant() 61 | } 62 | 63 | func (a AeadAlgorithm) isAlgorithmVariant() {} 64 | 65 | func (a *AeadAlgorithm) ToWireInterface() interface{} { 66 | return a.variant.ToWireInterface() 67 | } 68 | func (a *AeadAlgorithm) GetAeadDefaultLengthTag() *AeadAlgorithmDefaultLengthTag { 69 | if alg, ok := a.variant.(*AeadAlgorithmDefaultLengthTag); ok { 70 | return alg 71 | } 72 | return nil 73 | } 74 | func (a *AeadAlgorithm) GetAeadShortenedTag() *AeadAlgorithmShortenedTag { 75 | if alg, ok := a.variant.(*AeadAlgorithmShortenedTag); ok { 76 | return alg 77 | } 78 | return nil 79 | } 80 | 81 | type AeadAlgorithmDefaultLengthTag struct { 82 | AeadAlg AeadAlgorithmType 83 | } 84 | 85 | func (a *AeadAlgorithmDefaultLengthTag) isAeadAlgorithmVariant() {} 86 | 87 | func (a *AeadAlgorithmDefaultLengthTag) ToWireInterface() interface{} { 88 | return &psaalgorithm.Algorithm{ 89 | Variant: &psaalgorithm.Algorithm_Aead_{ 90 | Aead: &psaalgorithm.Algorithm_Aead{ 91 | Variant: &psaalgorithm.Algorithm_Aead_AeadWithDefaultLengthTag_{ 92 | AeadWithDefaultLengthTag: psaalgorithm.Algorithm_Aead_AeadWithDefaultLengthTag(a.AeadAlg), 93 | }, 94 | }, 95 | }, 96 | } 97 | } 98 | 99 | type AeadAlgorithmShortenedTag struct { 100 | AeadAlg AeadAlgorithmType 101 | TagLength uint32 102 | } 103 | 104 | func (a *AeadAlgorithmShortenedTag) isAeadAlgorithmVariant() {} 105 | 106 | func (a *AeadAlgorithmShortenedTag) ToWireInterface() interface{} { 107 | return &psaalgorithm.Algorithm{ 108 | Variant: &psaalgorithm.Algorithm_Aead_{ 109 | Aead: &psaalgorithm.Algorithm_Aead{ 110 | Variant: &psaalgorithm.Algorithm_Aead_AeadWithShortenedTag_{ 111 | AeadWithShortenedTag: &psaalgorithm.Algorithm_Aead_AeadWithShortenedTag{ 112 | AeadAlg: psaalgorithm.Algorithm_Aead_AeadWithDefaultLengthTag(a.AeadAlg), 113 | TagLength: a.TagLength, 114 | }, 115 | }, 116 | }, 117 | }, 118 | } 119 | } 120 | 121 | func newAeadFromWire(a *psaalgorithm.Algorithm_Aead) (*AeadAlgorithm, error) { 122 | switch linealg := a.Variant.(type) { 123 | case *psaalgorithm.Algorithm_Aead_AeadWithDefaultLengthTag_: 124 | return &AeadAlgorithm{ 125 | variant: &AeadAlgorithmDefaultLengthTag{ 126 | AeadAlg: AeadAlgorithmType(linealg.AeadWithDefaultLengthTag), 127 | }, 128 | }, nil 129 | case *psaalgorithm.Algorithm_Aead_AeadWithShortenedTag_: 130 | return &AeadAlgorithm{ 131 | variant: &AeadAlgorithmShortenedTag{ 132 | AeadAlg: AeadAlgorithmType(linealg.AeadWithShortenedTag.AeadAlg), 133 | TagLength: linealg.AeadWithShortenedTag.TagLength, 134 | }, 135 | }, nil 136 | default: 137 | return nil, fmt.Errorf("unexpected type encountered decoding aead algorithm: %v", reflect.TypeOf(linealg)) 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /parsec/algorithm/algorithm.go: -------------------------------------------------------------------------------- 1 | package algorithm 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 8 | ) 9 | 10 | type toWire interface { 11 | ToWireInterface() interface{} 12 | } 13 | 14 | type algorithmVariant interface { 15 | toWire 16 | isAlgorithmVariant() 17 | } 18 | 19 | type Algorithm struct { 20 | // Types that are assignable to Variant: 21 | // *Algorithm_None_ 22 | // *Algorithm_Hash_ 23 | // *Algorithm_Mac_ 24 | // *Algorithm_Cipher_ 25 | // *Algorithm_Aead_ 26 | // *Algorithm_AsymmetricSignature_ 27 | // *Algorithm_AsymmetricEncryption_ 28 | // *Algorithm_KeyAgreement_ 29 | // *Algorithm_KeyDerivation_ 30 | 31 | variant algorithmVariant 32 | } 33 | 34 | func (a *Algorithm) ToWireInterface() interface{} { 35 | if a.variant == nil { 36 | return nil 37 | } 38 | return a.variant.ToWireInterface() 39 | } 40 | 41 | func (a *Algorithm) GetAsymmetricSignature() *AsymmetricSignatureAlgorithm { 42 | if sub, ok := a.variant.(*AsymmetricSignatureAlgorithm); ok { 43 | return sub 44 | } 45 | return nil 46 | } 47 | 48 | func (a *Algorithm) GetAsymmetricEncryption() *AsymmetricEncryptionAlgorithm { 49 | if sub, ok := a.variant.(*AsymmetricEncryptionAlgorithm); ok { 50 | return sub 51 | } 52 | return nil 53 | } 54 | 55 | func (a *Algorithm) GetCipher() *Cipher { 56 | if sub, ok := a.variant.(*Cipher); ok { 57 | return sub 58 | } 59 | return nil 60 | } 61 | func (a *Algorithm) GetAead() *AeadAlgorithm { 62 | if sub, ok := a.variant.(*AeadAlgorithm); ok { 63 | return sub 64 | } 65 | return nil 66 | } 67 | 68 | func (a *Algorithm) GetHash() *HashAlgorithm { 69 | if sub, ok := a.variant.(*HashAlgorithm); ok { 70 | return sub 71 | } 72 | return nil 73 | } 74 | 75 | func NewAlgorithmFromWireInterface(op interface{}) (*Algorithm, error) { 76 | var algvar algorithmVariant 77 | var err error 78 | wireAlg, ok := op.(*psaalgorithm.Algorithm) 79 | if !ok { 80 | return nil, fmt.Errorf("expected psaalgorithm.Algorithm, got %v", reflect.TypeOf(op)) 81 | } 82 | if a := wireAlg.GetAsymmetricSignature(); a != nil { 83 | algvar, err = newAsymmetricSignatureFromWire(a) 84 | } 85 | if a := wireAlg.GetAsymmetricEncryption(); a != nil { 86 | algvar, err = newAsymmetricEncryptionFromWire(a) 87 | } 88 | if a := wireAlg.GetAead(); a != nil { 89 | algvar, err = newAeadFromWire(a) 90 | } 91 | if a := wireAlg.GetCipher(); a != psaalgorithm.Algorithm_CIPHER_NONE { 92 | algvar, err = newCipherFromWire(a) 93 | } 94 | if a := wireAlg.GetHash(); a != psaalgorithm.Algorithm_HASH_NONE { 95 | algvar, err = newHashFromWire(a) 96 | } 97 | if a := wireAlg.GetKeyAgreement(); a != nil { 98 | algvar, err = newKeyAgreementFromWire(a) 99 | } 100 | if a := wireAlg.GetKeyDerivation(); a != nil { 101 | algvar, err = newKeyDerivationFromWire(a) 102 | } 103 | if a := wireAlg.GetMac(); a != nil { 104 | algvar, err = newMacFromWire(a) 105 | } 106 | // Not doing none 107 | 108 | if err != nil { 109 | return nil, err 110 | } 111 | if algvar != nil { 112 | return &Algorithm{ 113 | variant: algvar, 114 | }, nil 115 | } 116 | return nil, fmt.Errorf("unknown algorithm type %v", reflect.TypeOf(op)) 117 | } 118 | -------------------------------------------------------------------------------- /parsec/algorithm/asymmetric_encryption.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 11 | ) 12 | 13 | type AsymmetricEncryptionFactory interface { 14 | RsaPkcs1V15Crypt() *Algorithm 15 | RsaOaep(hashAlg HashAlgorithmType) *Algorithm 16 | } 17 | 18 | type asymmetricEncryptionFactory struct{} 19 | 20 | func NewAsymmetricEncryption() AsymmetricEncryptionFactory { 21 | return &asymmetricEncryptionFactory{} 22 | } 23 | 24 | func (a *asymmetricEncryptionFactory) RsaPkcs1V15Crypt() *Algorithm { 25 | return &Algorithm{ 26 | variant: &AsymmetricEncryptionAlgorithm{ 27 | variant: &AsymmetricEncryptionRsaPkcs1V15Crypt{}, 28 | }, 29 | } 30 | } 31 | 32 | func (a *asymmetricEncryptionFactory) RsaOaep(hashAlg HashAlgorithmType) *Algorithm { 33 | return &Algorithm{ 34 | variant: &AsymmetricEncryptionAlgorithm{ 35 | variant: &AsymmetricEncryptionRsaOaep{ 36 | HashAlg: hashAlg, 37 | }, 38 | }, 39 | } 40 | } 41 | 42 | type AsymmetricEncryptionAlgorithm struct { 43 | // *AsymmetricEncryptionRsaPkcs1V15Crypt 44 | // *AsymmetricEncryptionRsaOaep 45 | variant asymmetricEncryptionAlgorithmVariant 46 | } 47 | 48 | type asymmetricEncryptionAlgorithmVariant interface { 49 | toWire 50 | // Algorithm 51 | isAsymmetricEncryptionAlgorithmVariant() 52 | } 53 | 54 | func (a *AsymmetricEncryptionAlgorithm) ToWireInterface() interface{} { 55 | return a.variant.ToWireInterface() 56 | } 57 | 58 | func (a *AsymmetricEncryptionAlgorithm) isAlgorithmVariant() {} 59 | 60 | func (a *AsymmetricEncryptionAlgorithm) GetRsaPkcs1V15Crypt() *AsymmetricEncryptionRsaPkcs1V15Crypt { 61 | if alg, ok := a.variant.(*AsymmetricEncryptionRsaPkcs1V15Crypt); ok { 62 | return alg 63 | } 64 | return nil 65 | } 66 | 67 | func (a *AsymmetricEncryptionAlgorithm) GetRsaOaep() *AsymmetricEncryptionRsaOaep { 68 | if alg, ok := a.variant.(*AsymmetricEncryptionRsaOaep); ok { 69 | return alg 70 | } 71 | return nil 72 | } 73 | 74 | func newAsymmetricEncryptionFromWire(a *psaalgorithm.Algorithm_AsymmetricEncryption) (*AsymmetricEncryptionAlgorithm, error) { 75 | if a == nil || a.Variant == nil { 76 | return nil, fmt.Errorf("nil argument passed") 77 | } 78 | switch alg := a.Variant.(type) { 79 | case *psaalgorithm.Algorithm_AsymmetricEncryption_RsaPkcs1V15Crypt_: 80 | return NewAsymmetricEncryption().RsaPkcs1V15Crypt().GetAsymmetricEncryption(), nil 81 | case *psaalgorithm.Algorithm_AsymmetricEncryption_RsaOaep_: 82 | return NewAsymmetricEncryption().RsaOaep(HashAlgorithmType(alg.RsaOaep.HashAlg)).GetAsymmetricEncryption(), nil 83 | default: 84 | return nil, fmt.Errorf("expected *AsymmetricEncryption compatible type, got %v", reflect.TypeOf(alg)) 85 | } 86 | } 87 | 88 | type AsymmetricEncryptionRsaPkcs1V15Crypt struct { 89 | } 90 | 91 | func (a *AsymmetricEncryptionRsaPkcs1V15Crypt) isAsymmetricEncryptionAlgorithmVariant() {} 92 | 93 | func (a *AsymmetricEncryptionRsaPkcs1V15Crypt) ToWireInterface() interface{} { 94 | return &psaalgorithm.Algorithm{ 95 | Variant: &psaalgorithm.Algorithm_AsymmetricEncryption_{ 96 | AsymmetricEncryption: &psaalgorithm.Algorithm_AsymmetricEncryption{ 97 | Variant: &psaalgorithm.Algorithm_AsymmetricEncryption_RsaPkcs1V15Crypt_{}, 98 | }, 99 | }, 100 | } 101 | } 102 | 103 | type AsymmetricEncryptionRsaOaep struct { 104 | HashAlg HashAlgorithmType 105 | } 106 | 107 | func (a *AsymmetricEncryptionRsaOaep) isAsymmetricEncryptionAlgorithmVariant() {} 108 | 109 | func (a *AsymmetricEncryptionRsaOaep) ToWireInterface() interface{} { 110 | return &psaalgorithm.Algorithm{ 111 | Variant: &psaalgorithm.Algorithm_AsymmetricEncryption_{ 112 | AsymmetricEncryption: &psaalgorithm.Algorithm_AsymmetricEncryption{ 113 | Variant: &psaalgorithm.Algorithm_AsymmetricEncryption_RsaOaep_{ 114 | RsaOaep: &psaalgorithm.Algorithm_AsymmetricEncryption_RsaOaep{ 115 | HashAlg: psaalgorithm.Algorithm_Hash(a.HashAlg), 116 | }, 117 | }, 118 | }, 119 | }, 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /parsec/algorithm/cipher.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm 5 | 6 | import ( 7 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 8 | ) 9 | 10 | type CipherModeType int32 11 | 12 | const ( 13 | CipherModeCIPHERNONE CipherModeType = 0 // This default variant should not be used. 14 | CipherModeSTREAMCIPHER CipherModeType = 1 15 | CipherModeCTR CipherModeType = 2 16 | CipherModeCFB CipherModeType = 3 17 | CipherModeOFB CipherModeType = 4 18 | CipherModeXTS CipherModeType = 5 19 | CipherModeECBNOPADDING CipherModeType = 6 20 | CipherModeCBCNOPADDING CipherModeType = 7 21 | CipherModeCBCPKCS7 CipherModeType = 8 22 | ) 23 | 24 | type Cipher struct { 25 | Mode CipherModeType 26 | } 27 | 28 | func (c *Cipher) isAlgorithmVariant() {} 29 | 30 | func (c *Cipher) ToWireInterface() interface{} { 31 | return &psaalgorithm.Algorithm{ 32 | Variant: &psaalgorithm.Algorithm_Cipher_{ 33 | // We've defined cipher mode to be same as protoc interface so we can cast safely 34 | Cipher: psaalgorithm.Algorithm_Cipher(c.Mode), 35 | }, 36 | } 37 | } 38 | 39 | func NewCipher(mode CipherModeType) *Algorithm { 40 | return &Algorithm{ 41 | variant: &Cipher{ 42 | Mode: mode, 43 | }, 44 | } 45 | } 46 | 47 | func newCipherFromWire(a psaalgorithm.Algorithm_Cipher) (*Cipher, error) { //nolint:unparam 48 | return &Cipher{ 49 | Mode: CipherModeType(a), 50 | }, nil 51 | } 52 | -------------------------------------------------------------------------------- /parsec/algorithm/hash.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 10 | ) 11 | 12 | type HashAlgorithmType uint32 13 | 14 | const ( 15 | HashAlgorithmTypeNONE HashAlgorithmType = 0 // This default variant should not be used. 16 | // Deprecated: Do not use. 17 | HashAlgorithmTypeMD2 HashAlgorithmType = 1 18 | // Deprecated: Do not use. 19 | HashAlgorithmTypeMD4 HashAlgorithmType = 2 20 | // Deprecated: Do not use. 21 | HashAlgorithmTypeMD5 HashAlgorithmType = 3 22 | HashAlgorithmTypeRIPEMD160 HashAlgorithmType = 4 23 | // Deprecated: Do not use. 24 | HashAlgorithmTypeSHA1 HashAlgorithmType = 5 25 | HashAlgorithmTypeSHA224 HashAlgorithmType = 6 26 | HashAlgorithmTypeSHA256 HashAlgorithmType = 7 27 | HashAlgorithmTypeSHA384 HashAlgorithmType = 8 28 | HashAlgorithmTypeSHA512 HashAlgorithmType = 9 29 | HashAlgorithmTypeSHA512_224 HashAlgorithmType = 10 30 | HashAlgorithmTypeSHA512_256 HashAlgorithmType = 11 31 | HashAlgorithmTypeSHA3_224 HashAlgorithmType = 12 32 | HashAlgorithmTypeSHA3_256 HashAlgorithmType = 13 33 | HashAlgorithmTypeSHA3_384 HashAlgorithmType = 14 34 | HashAlgorithmTypeSHA3_512 HashAlgorithmType = 15 35 | ) 36 | 37 | //nolint:gocyclo 38 | func (a HashAlgorithmType) String() string { 39 | switch a { 40 | case HashAlgorithmTypeNONE: 41 | return "HASH_NONE" 42 | case HashAlgorithmTypeMD2: 43 | return "MD2" 44 | case HashAlgorithmTypeMD4: 45 | return "MD4" 46 | case HashAlgorithmTypeMD5: 47 | return "MD5" 48 | case HashAlgorithmTypeRIPEMD160: 49 | return "RIPEMD160" 50 | case HashAlgorithmTypeSHA1: 51 | return "SHA_1" 52 | case HashAlgorithmTypeSHA224: 53 | return "SHA_224" 54 | case HashAlgorithmTypeSHA256: 55 | return "SHA_256" 56 | case HashAlgorithmTypeSHA384: 57 | return "SHA_384" 58 | case HashAlgorithmTypeSHA512: 59 | return "SHA_512" 60 | case HashAlgorithmTypeSHA512_224: 61 | return "SHA_512_224" 62 | case HashAlgorithmTypeSHA512_256: 63 | return "SHA_512_256" 64 | case HashAlgorithmTypeSHA3_224: 65 | return "SHA3_224" 66 | case HashAlgorithmTypeSHA3_256: 67 | return "SHA3_256" 68 | case HashAlgorithmTypeSHA3_384: 69 | return "SHA3_384" 70 | case HashAlgorithmTypeSHA3_512: 71 | return "SHA3_512" 72 | } 73 | return "" 74 | } 75 | 76 | type HashAlgorithm struct { 77 | HashAlg HashAlgorithmType 78 | } 79 | 80 | func NewHashAlgorithm(h HashAlgorithmType) *Algorithm { 81 | return &Algorithm{ 82 | variant: &HashAlgorithm{ 83 | HashAlg: h, 84 | }, 85 | } 86 | } 87 | 88 | func (a HashAlgorithm) String() string { 89 | return a.HashAlg.String() 90 | } 91 | 92 | func (a HashAlgorithm) isAlgorithmVariant() {} 93 | func (a *HashAlgorithm) ToWireInterface() interface{} { 94 | return psaalgorithm.Algorithm{ 95 | Variant: &psaalgorithm.Algorithm_Hash_{ 96 | // We've defined HashAlg to be same as protoc interface so we can cast safely 97 | Hash: psaalgorithm.Algorithm_Hash(a.HashAlg), 98 | }, 99 | } 100 | } 101 | 102 | func newHashFromWire(a psaalgorithm.Algorithm_Hash) (algorithmVariant, error) { 103 | return nil, fmt.Errorf("not implemented") 104 | } 105 | -------------------------------------------------------------------------------- /parsec/algorithm/keyagreement.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 11 | ) 12 | 13 | type KeyAgreementFactory interface { 14 | RawFFDH() *Algorithm 15 | RawECDH() *Algorithm 16 | FFDH(*KeyDerivation) *Algorithm 17 | ECDH(*KeyDerivation) *Algorithm 18 | } 19 | 20 | func NewKeyAgreement() KeyAgreementFactory { 21 | return &keyAgreementFactory{} 22 | } 23 | 24 | type keyAgreementFactory struct{} 25 | 26 | func (f *keyAgreementFactory) RawFFDH() *Algorithm { 27 | return &Algorithm{ 28 | variant: &KeyAgreement{ 29 | variant: &KeyAgreementRaw{ 30 | RawAlg: KeyAgreementFFDH, 31 | }, 32 | }, 33 | } 34 | } 35 | func (f *keyAgreementFactory) RawECDH() *Algorithm { 36 | return &Algorithm{ 37 | variant: &KeyAgreement{ 38 | variant: &KeyAgreementRaw{ 39 | RawAlg: KeyAgreementECDH, 40 | }, 41 | }, 42 | } 43 | } 44 | func (f *keyAgreementFactory) FFDH(kd *KeyDerivation) *Algorithm { 45 | return &Algorithm{ 46 | variant: &KeyAgreement{ 47 | variant: &KeyAgreementWithKeyDerivation{ 48 | DerivationAlg: kd, 49 | KaAlg: KeyAgreementFFDH, 50 | }, 51 | }, 52 | } 53 | } 54 | func (f *keyAgreementFactory) ECDH(kd *KeyDerivation) *Algorithm { 55 | return &Algorithm{ 56 | variant: &KeyAgreement{ 57 | variant: &KeyAgreementWithKeyDerivation{ 58 | DerivationAlg: kd, 59 | KaAlg: KeyAgreementECDH, 60 | }, 61 | }, 62 | } 63 | } 64 | 65 | type KeyAgreementRawType int32 66 | 67 | const ( 68 | KeyAgreementRAWNONE KeyAgreementRawType = 0 // This default variant should not be used. 69 | KeyAgreementFFDH KeyAgreementRawType = 1 70 | KeyAgreementECDH KeyAgreementRawType = 2 71 | ) 72 | 73 | func newKeyAgreementFromWire(a *psaalgorithm.Algorithm_KeyAgreement) (*KeyAgreement, error) { 74 | switch linealg := a.Variant.(type) { 75 | case *psaalgorithm.Algorithm_KeyAgreement_Raw_: 76 | return &KeyAgreement{ 77 | variant: &KeyAgreementRaw{ 78 | RawAlg: KeyAgreementRawType(linealg.Raw), 79 | }, 80 | }, nil 81 | case *psaalgorithm.Algorithm_KeyAgreement_WithKeyDerivation_: 82 | kdf, err := newKeyDerivationFromWire(linealg.WithKeyDerivation.KdfAlg) 83 | if err != nil { 84 | return nil, err 85 | } 86 | return &KeyAgreement{ 87 | variant: &KeyAgreementWithKeyDerivation{ 88 | KaAlg: KeyAgreementRawType(linealg.WithKeyDerivation.KaAlg), 89 | DerivationAlg: kdf, 90 | }, 91 | }, nil 92 | default: 93 | return nil, fmt.Errorf("unexpected type when decoding key agreement algorithm: %v", reflect.TypeOf(linealg)) 94 | } 95 | } 96 | 97 | type KeyAgreement struct { 98 | // *KeyAgreementRaw 99 | // *KeyAgreementWithKeyDerivation 100 | variant keyAgreementVariant 101 | } 102 | 103 | func (a *KeyAgreement) isAlgorithmVariant() {} 104 | 105 | func (a *KeyAgreement) ToWireInterface() interface{} { 106 | return a.variant.ToWireInterface() 107 | } 108 | 109 | type keyAgreementVariant interface { 110 | toWire 111 | isKeyAgreementVariant() 112 | } 113 | 114 | func (a *KeyAgreement) GetRaw() *KeyAgreementRaw { 115 | if alg, ok := a.variant.(*KeyAgreementRaw); ok { 116 | return alg 117 | } 118 | return nil 119 | } 120 | func (a *KeyAgreement) GetWithKeyDerivation() *KeyAgreementWithKeyDerivation { 121 | if alg, ok := a.variant.(*KeyAgreementWithKeyDerivation); ok { 122 | return alg 123 | } 124 | return nil 125 | } 126 | 127 | type KeyAgreementRaw struct { 128 | RawAlg KeyAgreementRawType 129 | } 130 | 131 | func (a *KeyAgreementRaw) isKeyAgreementVariant() {} 132 | func (a *KeyAgreementRaw) ToWireInterface() interface{} { 133 | return &psaalgorithm.Algorithm{ 134 | Variant: &psaalgorithm.Algorithm_KeyAgreement_{ 135 | KeyAgreement: &psaalgorithm.Algorithm_KeyAgreement{ 136 | Variant: &psaalgorithm.Algorithm_KeyAgreement_Raw_{ 137 | Raw: psaalgorithm.Algorithm_KeyAgreement_Raw(a.RawAlg), 138 | }, 139 | }, 140 | }, 141 | } 142 | } 143 | 144 | type KeyAgreementWithKeyDerivation struct { 145 | KaAlg KeyAgreementRawType 146 | DerivationAlg *KeyDerivation 147 | } 148 | 149 | func (a *KeyAgreementWithKeyDerivation) isKeyAgreementVariant() {} 150 | func (a *KeyAgreementWithKeyDerivation) ToWireInterface() interface{} { 151 | return &psaalgorithm.Algorithm{ 152 | Variant: &psaalgorithm.Algorithm_KeyAgreement_{ 153 | KeyAgreement: &psaalgorithm.Algorithm_KeyAgreement{ 154 | Variant: &psaalgorithm.Algorithm_KeyAgreement_WithKeyDerivation_{ 155 | WithKeyDerivation: &psaalgorithm.Algorithm_KeyAgreement_WithKeyDerivation{ 156 | KaAlg: psaalgorithm.Algorithm_KeyAgreement_Raw(a.KaAlg), 157 | KdfAlg: a.DerivationAlg.variant.toWireInterfaceSpecific(), 158 | }, 159 | }, 160 | }, 161 | }, 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /parsec/algorithm/keyderivation.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 11 | ) 12 | 13 | type keyDerivationFactory struct{} 14 | 15 | type KeyDerivationFactory interface { 16 | Hkdf(hashAlg HashAlgorithmType) *Algorithm 17 | TLS12PRF(hashAlg HashAlgorithmType) *Algorithm 18 | TLS12PSKToMs(hashAlg HashAlgorithmType) *Algorithm 19 | } 20 | 21 | func NewKeyDerivation() KeyDerivationFactory { 22 | return &keyDerivationFactory{} 23 | } 24 | 25 | func (f *keyDerivationFactory) Hkdf(hashAlg HashAlgorithmType) *Algorithm { 26 | return &Algorithm{ 27 | variant: &KeyDerivation{ 28 | variant: &KeyDerivationHkdf{ 29 | HashAlg: hashAlg, 30 | }, 31 | }, 32 | } 33 | } 34 | func (f *keyDerivationFactory) TLS12PRF(hashAlg HashAlgorithmType) *Algorithm { 35 | return &Algorithm{ 36 | variant: &KeyDerivation{ 37 | variant: &KeyDerivationTLS12Prf{ 38 | HashAlg: hashAlg, 39 | }, 40 | }, 41 | } 42 | } 43 | func (f *keyDerivationFactory) TLS12PSKToMs(hashAlg HashAlgorithmType) *Algorithm { 44 | return &Algorithm{ 45 | variant: &KeyDerivation{ 46 | variant: &KeyDerivationTLS12PskToMs{ 47 | HashAlg: hashAlg, 48 | }, 49 | }, 50 | } 51 | } 52 | 53 | type KeyDerivation struct { 54 | // *Algorithm_KeyDerivation_Hkdf_ 55 | // *Algorithm_KeyDerivation_Tls12Prf_ 56 | // *Algorithm_KeyDerivation_Tls12PskToMs_ 57 | variant keyDerivationVariant 58 | } 59 | 60 | func (a *KeyDerivation) isAlgorithmVariant() {} 61 | func (a *KeyDerivation) ToWireInterface() interface{} { 62 | return a.variant.ToWireInterface() 63 | } 64 | 65 | type keyDerivationVariant interface { 66 | toWire 67 | isKeyDerivationVariant() 68 | toWireInterfaceSpecific() *psaalgorithm.Algorithm_KeyDerivation 69 | } 70 | 71 | func (a *KeyDerivation) GetKeyDerivationHkdf() *KeyDerivationHkdf { 72 | if alg, ok := a.variant.(*KeyDerivationHkdf); ok { 73 | return alg 74 | } 75 | return nil 76 | } 77 | 78 | func (a *KeyDerivation) GetKeyDerivationTLS12Prf() *KeyDerivationTLS12Prf { 79 | if alg, ok := a.variant.(*KeyDerivationTLS12Prf); ok { 80 | return alg 81 | } 82 | return nil 83 | } 84 | 85 | func (a *KeyDerivation) GetKeyDerivationTLS12PskToMs() *KeyDerivationTLS12PskToMs { 86 | if alg, ok := a.variant.(*KeyDerivationTLS12PskToMs); ok { 87 | return alg 88 | } 89 | return nil 90 | } 91 | 92 | type KeyDerivationHkdf struct { 93 | HashAlg HashAlgorithmType 94 | } 95 | 96 | func (a *KeyDerivationHkdf) isKeyDerivationVariant() {} 97 | func (a *KeyDerivationHkdf) ToWireInterface() interface{} { 98 | return &psaalgorithm.Algorithm{ 99 | Variant: &psaalgorithm.Algorithm_KeyDerivation_{ 100 | KeyDerivation: a.toWireInterfaceSpecific(), 101 | }, 102 | } 103 | } 104 | 105 | func (a *KeyDerivationHkdf) toWireInterfaceSpecific() *psaalgorithm.Algorithm_KeyDerivation { 106 | return &psaalgorithm.Algorithm_KeyDerivation{ 107 | Variant: &psaalgorithm.Algorithm_KeyDerivation_Hkdf_{ 108 | Hkdf: &psaalgorithm.Algorithm_KeyDerivation_Hkdf{ 109 | HashAlg: psaalgorithm.Algorithm_Hash(a.HashAlg), 110 | }, 111 | }, 112 | } 113 | } 114 | 115 | type KeyDerivationTLS12Prf struct { 116 | HashAlg HashAlgorithmType 117 | } 118 | 119 | func (a *KeyDerivationTLS12Prf) isKeyDerivationVariant() {} 120 | func (a *KeyDerivationTLS12Prf) ToWireInterface() interface{} { 121 | return &psaalgorithm.Algorithm{ 122 | Variant: &psaalgorithm.Algorithm_KeyDerivation_{ 123 | KeyDerivation: a.toWireInterfaceSpecific(), 124 | }, 125 | } 126 | } 127 | func (a *KeyDerivationTLS12Prf) toWireInterfaceSpecific() *psaalgorithm.Algorithm_KeyDerivation { 128 | return &psaalgorithm.Algorithm_KeyDerivation{ 129 | Variant: &psaalgorithm.Algorithm_KeyDerivation_Tls12Prf_{ 130 | Tls12Prf: &psaalgorithm.Algorithm_KeyDerivation_Tls12Prf{ 131 | HashAlg: psaalgorithm.Algorithm_Hash(a.HashAlg), 132 | }, 133 | }, 134 | } 135 | } 136 | 137 | type KeyDerivationTLS12PskToMs struct { 138 | HashAlg HashAlgorithmType 139 | } 140 | 141 | func (a *KeyDerivationTLS12PskToMs) isKeyDerivationVariant() {} 142 | 143 | func (a *KeyDerivationTLS12PskToMs) ToWireInterface() interface{} { 144 | return &psaalgorithm.Algorithm{ 145 | Variant: &psaalgorithm.Algorithm_KeyDerivation_{ 146 | KeyDerivation: a.toWireInterfaceSpecific(), 147 | }, 148 | } 149 | } 150 | func (a *KeyDerivationTLS12PskToMs) toWireInterfaceSpecific() *psaalgorithm.Algorithm_KeyDerivation { 151 | return &psaalgorithm.Algorithm_KeyDerivation{ 152 | Variant: &psaalgorithm.Algorithm_KeyDerivation_Tls12PskToMs_{ 153 | Tls12PskToMs: &psaalgorithm.Algorithm_KeyDerivation_Tls12PskToMs{ 154 | HashAlg: psaalgorithm.Algorithm_Hash(a.HashAlg), 155 | }, 156 | }, 157 | } 158 | } 159 | 160 | func newKeyDerivationFromWire(a *psaalgorithm.Algorithm_KeyDerivation) (*KeyDerivation, error) { 161 | switch linealg := a.Variant.(type) { 162 | case *psaalgorithm.Algorithm_KeyDerivation_Hkdf_: 163 | return &KeyDerivation{ 164 | variant: &KeyDerivationHkdf{ 165 | HashAlg: HashAlgorithmType(linealg.Hkdf.HashAlg), 166 | }, 167 | }, nil 168 | case *psaalgorithm.Algorithm_KeyDerivation_Tls12Prf_: 169 | return &KeyDerivation{ 170 | variant: &KeyDerivationTLS12Prf{ 171 | HashAlg: HashAlgorithmType(linealg.Tls12Prf.HashAlg), 172 | }, 173 | }, nil 174 | case *psaalgorithm.Algorithm_KeyDerivation_Tls12PskToMs_: 175 | return &KeyDerivation{ 176 | variant: &KeyDerivationTLS12PskToMs{ 177 | HashAlg: HashAlgorithmType(linealg.Tls12PskToMs.HashAlg), 178 | }, 179 | }, nil 180 | default: 181 | return nil, fmt.Errorf("unexpected type encountered decoding key derivation algorithm: %v", reflect.TypeOf(linealg)) 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /parsec/algorithm/test/algorithm_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm_test 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 10 | ) 11 | 12 | func TestAlgorithmSubclasses(t *testing.T) { 13 | a1 := algorithm.NewCipher(algorithm.CipherModeCFB) 14 | if a1 == nil { 15 | t.Fatal("Got nil algorithm") 16 | } 17 | if a1.GetAead() != nil || a1.GetAsymmetricSignature() != nil { 18 | t.Error("Expected only to get non nil subtype for cipher") 19 | } 20 | if a1.GetCipher() == nil { 21 | t.Error("Could not retrieve cipher from generic algorithm") 22 | } 23 | 24 | a2 := algorithm.NewAead().Aead(algorithm.AeadAlgorithmChacha20Poly1305) 25 | if a2 == nil { 26 | t.Fatal("Got nil algorithm") 27 | } 28 | if a2.GetCipher() != nil || a2.GetAsymmetricSignature() != nil { 29 | t.Error("Expected only to get non nil subtype for cipher") 30 | } 31 | if ca := a2.GetAead(); ca == nil { 32 | t.Error("Could not retrieve Aead from generic algorithm") 33 | } else { 34 | if cavar := ca.GetAeadShortenedTag(); cavar != nil { 35 | t.Error("got shortened aead algorithm and was expecting full length") 36 | } else { 37 | if cavar := ca.GetAeadDefaultLengthTag(); cavar == nil { 38 | t.Error("could not get default length aead") 39 | } else if cavar.AeadAlg != algorithm.AeadAlgorithmChacha20Poly1305 { 40 | t.Errorf("Expected to have alg type of AeadAlgorithmChacha20Poly1305 but got %v", cavar.AeadAlg) 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /parsec/algorithm/test/hash_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm_test 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 10 | ) 11 | 12 | func TestHash(t *testing.T) { 13 | // Make sure that HashAlgorithm can be assigned to Algorithm 14 | type algstruct struct { 15 | alg *algorithm.Algorithm 16 | } 17 | 18 | a := &algstruct{ 19 | alg: algorithm.NewHashAlgorithm(algorithm.HashAlgorithmTypeMD5), //nolint:staticcheck // this is test code and we're testing this algorithm 20 | } 21 | if a.alg == nil { 22 | t.Fatal("could not construct algorithm structure") 23 | } 24 | 25 | if ha := a.alg.GetHash(); ha != nil { 26 | if ha.HashAlg != algorithm.HashAlgorithmTypeMD5 { //nolint:staticcheck // this is test code and we're testing this algorithm 27 | t.Fatalf("Expected alg to be of type HashAlgorithmTypeMD5, was actually %v", ha.HashAlg) 28 | } 29 | } else { 30 | t.Fatal("Expected alg element to be Hash Algorithm, it wasn't") 31 | } 32 | } 33 | 34 | func TestHashString(t *testing.T) { 35 | if algorithm.HashAlgorithmTypeMD2.String() != "MD2" { //nolint:staticcheck // this is test code and we're testing this algorithm 36 | t.Fatal("Incorrect string value from hash enum") 37 | } 38 | if algorithm.NewHashAlgorithm(algorithm.HashAlgorithmTypeSHA256).GetHash().String() != "SHA_256" { 39 | t.Fatal("Incorrect string value for hash algorithm") 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /parsec/algorithm/test/keyderivation_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package algorithm_test 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 10 | ) 11 | 12 | func TestKeyDerivationNew(t *testing.T) { 13 | algorithm.NewKeyDerivation().Hkdf(algorithm.HashAlgorithmTypeMD2) //nolint:staticcheck // this is test code and we're testing this algorithm 14 | } 15 | -------------------------------------------------------------------------------- /parsec/authenticator.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package parsec 5 | 6 | import "github.com/parallaxsecond/parsec-client-go/interface/auth" 7 | 8 | // AuthenticatorType enum to identify authenticators 9 | type AuthenticatorType uint8 10 | 11 | // Authenticator Types 12 | const ( 13 | AuthNoAuth AuthenticatorType = AuthenticatorType(auth.AuthNoAuth) 14 | // Direct authentication 15 | AuthDirect AuthenticatorType = AuthenticatorType(auth.AuthDirect) 16 | // JSON Web Tokens (JWT) authentication (not currently supported) 17 | AuthJwt AuthenticatorType = AuthenticatorType(auth.AuthJwt) 18 | // Unix peer credentials authentication 19 | AuthUnixPeerCredentials AuthenticatorType = AuthenticatorType(auth.AuthUnixPeerCredentials) 20 | // Authentication verifying a JWT SPIFFE Verifiable Identity Document 21 | AuthJwtSvid AuthenticatorType = AuthenticatorType(auth.AuthJwtSvid) 22 | ) 23 | 24 | // AuthenticatorInfo contains information about an authenticator. 25 | // Id is the id used to select the authenticator 26 | // Name name of the authenticator 27 | type AuthenticatorInfo struct { 28 | ID AuthenticatorType 29 | Description string 30 | VersionMaj uint32 31 | VersionMin uint32 32 | VersionRev uint32 33 | } 34 | 35 | // Authenticator object providing authenticator functionality to the basic client. 36 | type Authenticator interface { 37 | toNativeAuthenticator() auth.Authenticator 38 | // GetAuthenticatorType return the type of this authenticator. 39 | GetAuthenticatorType() AuthenticatorType 40 | } 41 | 42 | // Internal implementation of authenticator - just wrapps the interface version. 43 | type authenticatorWrapper struct { 44 | nativeAuth auth.Authenticator 45 | } 46 | 47 | func (w *authenticatorWrapper) toNativeAuthenticator() auth.Authenticator { 48 | return w.nativeAuth 49 | } 50 | 51 | // GetAuthenticatorType return the type of this authenticator. 52 | func (w *authenticatorWrapper) GetAuthenticatorType() AuthenticatorType { 53 | return AuthenticatorType(w.nativeAuth.GetType()) 54 | } 55 | 56 | // NewNoAuthAuthenticator creates an authenticator that does no authentication. Used only for testing, 57 | // or for initial connection when discovering the available authenticators to select a default. 58 | func NewNoAuthAuthenticator() Authenticator { 59 | return &authenticatorWrapper{ 60 | nativeAuth: auth.NewNoAuthAuthenticator(), 61 | } 62 | } 63 | 64 | // NewDirectAuthenticator creates an authenticator which uses the supplied appName as the means of authentication 65 | // with the parsec service 66 | func NewDirectAuthenticator(appName string) Authenticator { 67 | return &authenticatorWrapper{ 68 | nativeAuth: auth.NewDirectAuthenticator(appName), 69 | } 70 | } 71 | 72 | // NewUnixPeerAuthenticator creates a new authenticator which uses current logged in user id as authentication 73 | // to the parsec service 74 | func NewUnixPeerAuthenticator() Authenticator { 75 | return &authenticatorWrapper{ 76 | nativeAuth: auth.NewUnixPeerAuthenticator(), 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /parsec/client_config.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package parsec 4 | 5 | import ( 6 | "github.com/parallaxsecond/parsec-client-go/interface/auth" 7 | "github.com/parallaxsecond/parsec-client-go/interface/connection" 8 | ) 9 | 10 | // ClientConfig holds a configuration for the basic client to be passed to InitClient 11 | // ClientConfig's methods use the Builder pattern to build configurations, e.g: 12 | // config := NewClientConfig().DirectAuthConfigData("myapp").Connection(myConn) 13 | type ClientConfig struct { 14 | authenticatorData map[auth.AuthenticationType]interface{} 15 | connection connection.Connection 16 | defaultProvider *ProviderID 17 | authenticator Authenticator 18 | } 19 | 20 | // NewClientConfig ceates a ClientConfig with defaults 21 | func NewClientConfig() *ClientConfig { 22 | config := ClientConfig{ 23 | authenticatorData: make(map[auth.AuthenticationType]interface{}), 24 | } 25 | return &config 26 | } 27 | 28 | // DirectAuthConfigData creates a new ClientConfig with the appName parameter set for Direct Authentication 29 | func DirectAuthConfigData(appName string) *ClientConfig { 30 | config := NewClientConfig() 31 | config.authenticatorData[auth.AuthDirect] = appName 32 | return config 33 | } 34 | 35 | // DirectAuthConfigData sets the appName parameter to use when using Direct Authentication 36 | func (config *ClientConfig) DirectAuthConfigData(appName string) *ClientConfig { 37 | config.authenticatorData[auth.AuthDirect] = appName 38 | return config 39 | } 40 | 41 | // Connection sets the conn.Connection object to use when connecting to the parsec service. 42 | // This is primarily used for testing purposes, to allow for mocking of the parsec service. 43 | func (config *ClientConfig) Connection(conn connection.Connection) *ClientConfig { 44 | config.connection = conn 45 | return config 46 | } 47 | 48 | // Provider set the provider to use. If this is set the basic client won't attempt to auto select 49 | // a provider, even if this one is not supported by the parsec service. 50 | func (config *ClientConfig) Provider(provider ProviderID) *ClientConfig { 51 | config.defaultProvider = &provider 52 | return config 53 | } 54 | 55 | // Authenticator sets the authenticator to use. If this is set, the basic client won't attempt to 56 | // auto select an authenticator even if this one is not supported by the parsec service 57 | func (config *ClientConfig) Authenticator(authenticator Authenticator) *ClientConfig { 58 | config.authenticator = authenticator 59 | return config 60 | } 61 | -------------------------------------------------------------------------------- /parsec/convert_utils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package parsec 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | "github.com/parallaxsecond/parsec-client-go/interface/auth" 11 | "github.com/parallaxsecond/parsec-client-go/interface/operations/listauthenticators" 12 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 13 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 14 | ) 15 | 16 | func newAuthenticatorInfoFromOp(inf *listauthenticators.AuthenticatorInfo) (*AuthenticatorInfo, error) { 17 | authid, err := auth.NewAuthenticationTypeFromU32(inf.Id) 18 | if err != nil { 19 | return nil, err 20 | } 21 | return &AuthenticatorInfo{ 22 | ID: AuthenticatorType(authid), 23 | Description: inf.Description, 24 | VersionMaj: inf.VersionMaj, 25 | VersionMin: inf.VersionMin, 26 | VersionRev: inf.VersionRev, 27 | }, nil 28 | } 29 | 30 | func hashAlgToWire(h algorithm.HashAlgorithmType) psaalgorithm.Algorithm_Hash { 31 | return psaalgorithm.Algorithm_Hash(h) 32 | } 33 | 34 | func algAsymmetricSigToWire(a *algorithm.AsymmetricSignatureAlgorithm) (*psaalgorithm.Algorithm_AsymmetricSignature, error) { 35 | aif := a.ToWireInterface() 36 | alg, ok := a.ToWireInterface().(*psaalgorithm.Algorithm) 37 | if !ok { 38 | return nil, fmt.Errorf("unexpected type expecting *psaalgorithm.Algorithm, got %v", reflect.TypeOf(aif)) 39 | } 40 | varalg := alg.GetAsymmetricSignature() 41 | if varalg == nil { 42 | return nil, fmt.Errorf("expected *psaalgorithm.Algorithm_AsymmetricSignature, but got nil") 43 | } 44 | return varalg, nil 45 | } 46 | 47 | func algAsymmetricEncryptionAlgToWire(a *algorithm.AsymmetricEncryptionAlgorithm) (*psaalgorithm.Algorithm_AsymmetricEncryption, error) { 48 | alg, ok := a.ToWireInterface().(*psaalgorithm.Algorithm) 49 | if !ok { 50 | return nil, fmt.Errorf("unexpected type expecting *psaalgorithm.Algorithm, got %v", reflect.TypeOf(alg)) 51 | } 52 | varalg := alg.GetAsymmetricEncryption() 53 | if varalg == nil { 54 | return nil, fmt.Errorf("expected *psaalgorithm.Algorithm_AsymmetricEncryption, but got nil") 55 | } 56 | return varalg, nil 57 | } 58 | 59 | func algCipherAlgToWire(a *algorithm.Cipher) (psaalgorithm.Algorithm_Cipher, error) { 60 | alg, ok := a.ToWireInterface().(*psaalgorithm.Algorithm) 61 | if !ok { 62 | return psaalgorithm.Algorithm_CIPHER_NONE, fmt.Errorf("unexpected type expecting *psaalgorithm.Algorithm, got %v", reflect.TypeOf(alg)) 63 | } 64 | varalg := alg.GetCipher() 65 | if varalg == psaalgorithm.Algorithm_CIPHER_NONE { 66 | return psaalgorithm.Algorithm_CIPHER_NONE, fmt.Errorf("expected *psaalgorithm.Algorithm_AsymmetricEncryption, but got nil") 67 | } 68 | return varalg, nil 69 | } 70 | 71 | func algAeadAlgToWire(a *algorithm.AeadAlgorithm) (*psaalgorithm.Algorithm_Aead, error) { 72 | alg, ok := a.ToWireInterface().(*psaalgorithm.Algorithm) 73 | if !ok { 74 | return nil, fmt.Errorf("unexpected type expecting *psaalgorithm.Algorithm, got %v", reflect.TypeOf(alg)) 75 | } 76 | varalg := alg.GetAead() 77 | if varalg == nil { 78 | return nil, fmt.Errorf("expected *psaalgorithm.Algorithm_Aead, but got nil") 79 | } 80 | return varalg, nil 81 | } 82 | 83 | func algMacAlgToWire(a *algorithm.MacAlgorithm) (*psaalgorithm.Algorithm_Mac, error) { 84 | alg, ok := a.ToWireInterface().(*psaalgorithm.Algorithm) 85 | if !ok { 86 | return nil, fmt.Errorf("unexpected type expecting *psaalgorithm.Algorithm, got %v", reflect.TypeOf(alg)) 87 | } 88 | varalg := alg.GetMac() 89 | if varalg == nil { 90 | return nil, fmt.Errorf("expected *psaalgorithm.Algorithm_Mac, but got nil") 91 | } 92 | return varalg, nil 93 | } 94 | 95 | func algKeyAgreementRawAlgToWire(a *algorithm.KeyAgreementRaw) (*psaalgorithm.Algorithm_KeyAgreement, error) { 96 | alg, ok := a.ToWireInterface().(*psaalgorithm.Algorithm) 97 | if !ok { 98 | return nil, fmt.Errorf("unexpected type expecting *psaalgorithm.Algorithm, got %v", reflect.TypeOf(alg)) 99 | } 100 | varalg := alg.GetKeyAgreement() 101 | if varalg == nil { 102 | return nil, fmt.Errorf("expected *psaalgorithm.Algorithm_KeyAgreement_Raw, but got nil") 103 | } 104 | return varalg, nil 105 | } 106 | -------------------------------------------------------------------------------- /parsec/default_attributes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package parsec 5 | 6 | import "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 7 | 8 | type DefaultKeyAttributeFactory interface { 9 | SigningKey() *KeyAttributes 10 | } 11 | 12 | type defaultKeyAttributeFactory struct{} 13 | 14 | func DefaultKeyAttribute() DefaultKeyAttributeFactory { 15 | return &defaultKeyAttributeFactory{} 16 | } 17 | 18 | func (f *defaultKeyAttributeFactory) SigningKey() *KeyAttributes { 19 | const keyBits = 2048 20 | const hashAlg = algorithm.HashAlgorithmTypeSHA256 21 | return &KeyAttributes{ 22 | KeyBits: keyBits, 23 | KeyType: NewKeyType().RsaKeyPair(), 24 | KeyPolicy: &KeyPolicy{ 25 | KeyAlgorithm: algorithm.NewAsymmetricSignature().RsaPkcs1V15Sign(hashAlg), 26 | KeyUsageFlags: &UsageFlags{ 27 | Cache: false, 28 | Copy: false, 29 | Decrypt: false, 30 | Derive: false, 31 | Encrypt: false, 32 | Export: false, 33 | SignHash: true, 34 | SignMessage: true, 35 | VerifyHash: true, 36 | VerifyMessage: true, 37 | }, 38 | }, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /parsec/keyinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package parsec 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | 10 | "github.com/parallaxsecond/parsec-client-go/interface/operations/listkeys" 11 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psaalgorithm" 12 | "github.com/parallaxsecond/parsec-client-go/interface/operations/psakeyattributes" 13 | "github.com/parallaxsecond/parsec-client-go/parsec/algorithm" 14 | ) 15 | 16 | type ToWire interface { 17 | ToWireInterface() interface{} 18 | } 19 | 20 | type UsageFlags struct { 21 | Export bool 22 | Copy bool 23 | Cache bool 24 | Encrypt bool 25 | Decrypt bool 26 | SignMessage bool 27 | VerifyMessage bool 28 | SignHash bool 29 | VerifyHash bool 30 | Derive bool 31 | } 32 | 33 | func (u *UsageFlags) toNativeWireInterface() *psakeyattributes.UsageFlags { 34 | return &psakeyattributes.UsageFlags{ 35 | Export: u.Export, 36 | Copy: u.Copy, 37 | Cache: u.Cache, 38 | Encrypt: u.Encrypt, 39 | Decrypt: u.Decrypt, 40 | SignMessage: u.SignMessage, 41 | VerifyMessage: u.VerifyMessage, 42 | VerifyHash: u.VerifyHash, 43 | SignHash: u.SignHash, 44 | Derive: u.Derive, 45 | } 46 | } 47 | 48 | type KeyPolicy struct { 49 | KeyUsageFlags *UsageFlags 50 | KeyAlgorithm *algorithm.Algorithm 51 | } 52 | 53 | func (kp *KeyPolicy) toNativeWireInterface() *psakeyattributes.KeyPolicy { 54 | kaif := kp.KeyAlgorithm.ToWireInterface() 55 | if kaif == nil { 56 | fmt.Println("no wire alg from kp.KeyAlgorithm") 57 | return nil 58 | } 59 | ka, ok := kaif.(*psaalgorithm.Algorithm) 60 | if !ok { 61 | fmt.Printf("kaif is wrong type, got %v\n", reflect.TypeOf(kaif)) 62 | return nil 63 | } 64 | 65 | return &psakeyattributes.KeyPolicy{ 66 | KeyAlgorithm: ka, 67 | KeyUsageFlags: kp.KeyUsageFlags.toNativeWireInterface(), 68 | } 69 | } 70 | 71 | type KeyAttributes struct { 72 | KeyType *KeyType 73 | KeyBits uint32 74 | KeyPolicy *KeyPolicy 75 | } 76 | 77 | func newKeyAttributesFromOp(ka *psakeyattributes.KeyAttributes) (*KeyAttributes, error) { //nolint:unparam 78 | return &KeyAttributes{ 79 | KeyBits: ka.KeyBits, 80 | // KeyPolicy: , 81 | }, nil 82 | // TODO finish this 83 | } 84 | 85 | func (ka *KeyAttributes) toWireInterface() (*psakeyattributes.KeyAttributes, error) { 86 | keytypeif := ka.KeyType.ToWireInterface() 87 | if keytypeif == nil { 88 | return nil, fmt.Errorf("nil keytype returned for wire interface") 89 | } 90 | keytype, ok := keytypeif.(*psakeyattributes.KeyType) 91 | if !ok { 92 | return nil, fmt.Errorf("incorrect type returned for keytype") 93 | } 94 | return &psakeyattributes.KeyAttributes{ 95 | KeyBits: ka.KeyBits, 96 | KeyType: keytype, 97 | KeyPolicy: ka.KeyPolicy.toNativeWireInterface(), 98 | }, nil 99 | } 100 | 101 | type KeyInfo struct { 102 | ProviderID ProviderID 103 | Name string 104 | Attributes *KeyAttributes 105 | } 106 | 107 | func newKeyInfoFromOp(wireinf *listkeys.KeyInfo) (*KeyInfo, error) { 108 | ka, err := newKeyAttributesFromOp(wireinf.Attributes) 109 | if err != nil { 110 | return nil, err 111 | } 112 | return &KeyInfo{ 113 | ProviderID: ProviderID(wireinf.ProviderId), 114 | Name: wireinf.Name, 115 | Attributes: ka, 116 | }, nil 117 | } 118 | -------------------------------------------------------------------------------- /parsec/mod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package parsec 5 | 6 | // The public interface of the Parsec Go Language client. 7 | -------------------------------------------------------------------------------- /parsec/provider.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package parsec 5 | 6 | import ( 7 | "github.com/parallaxsecond/parsec-client-go/interface/operations/listproviders" 8 | "github.com/parallaxsecond/parsec-client-go/interface/requests" 9 | ) 10 | 11 | // ProviderID for providers 12 | type ProviderID uint8 13 | 14 | // Provider UUIDs 15 | const ( 16 | ProviderCore ProviderID = 0 17 | ProviderMBed ProviderID = 1 18 | ProviderPKCS11 ProviderID = 2 19 | ProviderTPM ProviderID = 3 20 | ProviderTrustedService ProviderID = 4 21 | ) 22 | 23 | // HasCrypto returns true if the provider supports crypto 24 | func (p *ProviderID) HasCrypto() bool { 25 | return *p != ProviderCore 26 | } 27 | 28 | func (p ProviderID) String() string { 29 | switch p { 30 | case ProviderCore: 31 | return "Core" 32 | case ProviderMBed: 33 | return "MBed" 34 | case ProviderPKCS11: 35 | return "PKCS11" 36 | case ProviderTPM: 37 | return "TPM" 38 | case ProviderTrustedService: 39 | return "TrustedService" 40 | default: 41 | return "Unknown" 42 | } 43 | } 44 | 45 | type ProviderInfo struct { 46 | UUID string 47 | Description string 48 | Vendor string 49 | VersionMaj uint32 50 | VersionMin uint32 51 | VersionRev uint32 52 | ID ProviderID 53 | } 54 | 55 | func newProviderIDFromOp(p requests.ProviderID) ProviderID { 56 | return ProviderID(p) 57 | } 58 | 59 | func newProviderInfoFromOp(inf *listproviders.ProviderInfo) *ProviderInfo { 60 | return &ProviderInfo{ 61 | UUID: inf.Uuid, 62 | Description: inf.Description, 63 | Vendor: inf.Vendor, 64 | VersionMaj: inf.VersionMaj, 65 | VersionMin: inf.VersionMin, 66 | ID: newProviderIDFromOp(requests.ProviderID(inf.Id)), 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /parsec/test/basic_client_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package test 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "io" 9 | "os" 10 | "testing" 11 | 12 | . "github.com/onsi/ginkgo" 13 | . "github.com/onsi/gomega" 14 | "github.com/parallaxsecond/parsec-client-go/interface/connection" 15 | "github.com/parallaxsecond/parsec-client-go/parsec" 16 | ) 17 | 18 | // loadTestData loads a list of test case json files and parses them into a map of TestCase objects, keyed by the testcase name. 19 | func loadTestData(fileNames []string) map[string]testCase { 20 | testMap := make(map[string]testCase) 21 | 22 | for _, fileName := range fileNames { 23 | jsonfile, err := os.Open(fileName) 24 | Expect(err).NotTo(HaveOccurred()) 25 | byteValue, err := io.ReadAll(jsonfile) 26 | Expect(err).NotTo(HaveOccurred()) 27 | var testSuite struct { 28 | Tests []testCase `json:"tests"` 29 | } 30 | 31 | err = json.Unmarshal(byteValue, &testSuite) 32 | fmt.Println(err) 33 | Expect(err).NotTo(HaveOccurred()) 34 | 35 | for _, tc := range testSuite.Tests { 36 | testMap[tc.Name] = tc 37 | } 38 | } 39 | 40 | return testMap 41 | } 42 | 43 | func TestRequests(t *testing.T) { 44 | RegisterFailHandler(Fail) 45 | RunSpecs(t, "requests package internal suite") 46 | } 47 | 48 | var _ = Describe("Basic Client provider behaviour", func() { 49 | testCases := loadTestData([]string{"list_providers.json", "list_authenticators.json"}) 50 | var connection connection.Connection 51 | BeforeEach(func() { 52 | connection = newMockConnectionFromTestCase([]testCase{testCases["auth_direct"], testCases["provider_mbed"]}) 53 | }) 54 | Context("Default", func() { 55 | It("should have mbed as default", func() { 56 | bc, err := parsec.CreateConfiguredClient(parsec.DirectAuthConfigData("testapp").Connection(connection)) 57 | Expect(err).NotTo(HaveOccurred()) 58 | Expect(bc).NotTo(BeNil()) 59 | 60 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderMBed)) 61 | }) 62 | }) 63 | Context("Set Implicit to Tpm", func() { 64 | It("Should allow us to change provider", func() { 65 | bc, err := parsec.CreateConfiguredClient(parsec.DirectAuthConfigData("testapp").Connection(connection)) 66 | Expect(err).NotTo(HaveOccurred()) 67 | Expect(bc).NotTo(BeNil()) 68 | bc.SetImplicitProvider(parsec.ProviderTPM) 69 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderTPM)) 70 | }) 71 | }) 72 | Describe("Auto selection of authenticator", func() { 73 | var tc []testCase 74 | JustBeforeEach(func() { 75 | connection = newMockConnectionFromTestCase(tc) 76 | }) 77 | Context("service supports only default", func() { 78 | BeforeEach(func() { 79 | tc = []testCase{testCases["auth_direct"], testCases["provider_mbed"]} 80 | }) 81 | It("Should return direct if we have direct auth data", func() { 82 | bc, err := parsec.CreateConfiguredClient(parsec.DirectAuthConfigData("testapp").Connection(connection)) 83 | Expect(err).NotTo(HaveOccurred()) 84 | Expect(bc).NotTo(BeNil()) 85 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderMBed)) 86 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthDirect)) 87 | }) 88 | It("Should return none if we have no direct auth data", func() { 89 | bc, err := parsec.CreateConfiguredClient(parsec.NewClientConfig().Connection(connection)) 90 | Expect(err).NotTo(HaveOccurred()) 91 | Expect(bc).NotTo(BeNil()) 92 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderMBed)) 93 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthNoAuth)) 94 | }) 95 | }) 96 | Context("service supports direct, unix", func() { 97 | BeforeEach(func() { 98 | tc = []testCase{testCases["auth_direct,unix"], testCases["provider_mbed"]} 99 | }) 100 | It("Should return direct if we have direct auth data", func() { 101 | bc, err := parsec.CreateConfiguredClient(parsec.DirectAuthConfigData("testapp").Connection(connection)) 102 | Expect(err).NotTo(HaveOccurred()) 103 | Expect(bc).NotTo(BeNil()) 104 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderMBed)) 105 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthDirect)) 106 | }) 107 | It("Should return unix if we have no direct auth data", func() { 108 | bc, err := parsec.CreateConfiguredClient(parsec.NewClientConfig().Connection(connection)) 109 | Expect(err).NotTo(HaveOccurred()) 110 | Expect(bc).NotTo(BeNil()) 111 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderMBed)) 112 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthUnixPeerCredentials)) 113 | }) 114 | }) 115 | Context("service supports unix,direct", func() { 116 | BeforeEach(func() { 117 | tc = []testCase{testCases["auth_unix,direct"], testCases["provider_mbed"]} 118 | }) 119 | It("Should return unix even if we have direct auth data", func() { 120 | bc, err := parsec.CreateConfiguredClient(parsec.DirectAuthConfigData("testapp").Connection(connection)) 121 | Expect(err).NotTo(HaveOccurred()) 122 | Expect(bc).NotTo(BeNil()) 123 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderMBed)) 124 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthUnixPeerCredentials)) 125 | }) 126 | It("Should return unix if we have no direct auth data", func() { 127 | bc, err := parsec.CreateConfiguredClient(parsec.NewClientConfig().Connection(connection)) 128 | Expect(err).NotTo(HaveOccurred()) 129 | Expect(bc).NotTo(BeNil()) 130 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderMBed)) 131 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthUnixPeerCredentials)) 132 | }) 133 | }) 134 | Context("service supports tpm,mbed providers", func() { 135 | BeforeEach(func() { 136 | tc = []testCase{testCases["auth_direct"], testCases["provider_tpm,mbed"]} 137 | }) 138 | It("Should return tpm provider", func() { 139 | bc, err := parsec.CreateConfiguredClient(parsec.DirectAuthConfigData("testapp").Connection(connection)) 140 | Expect(err).NotTo(HaveOccurred()) 141 | Expect(bc).NotTo(BeNil()) 142 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderTPM)) 143 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthDirect)) 144 | }) 145 | }) 146 | }) 147 | Describe("Set authenticator and provider in client config", func() { 148 | Context("set provider to tpm and authentictor to unix", func() { 149 | It("Should return configured provider and authenticator, and not call parsec service", func() { 150 | config := parsec.NewClientConfig(). 151 | Provider(parsec.ProviderTPM). 152 | Authenticator(parsec.NewUnixPeerAuthenticator()). 153 | Connection(newNoopConnection()) // This connection will fail the test if it is called 154 | bc, err := parsec.CreateConfiguredClient(config) 155 | Expect(err).NotTo(HaveOccurred()) 156 | Expect(bc).NotTo(BeNil()) 157 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderTPM)) 158 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthUnixPeerCredentials)) 159 | }) 160 | }) 161 | }) 162 | Describe("Test naked creation", func() { 163 | It("Should be configured with core provider and no auth authenticator", func() { 164 | bc, err := parsec.CreateNakedClient() 165 | Expect(err).NotTo(HaveOccurred()) 166 | Expect(bc).NotTo(BeNil()) 167 | Expect(bc.GetImplicitProvider()).To(Equal(parsec.ProviderCore)) 168 | Expect(bc.GetAuthenticatorType()).To(Equal(parsec.AuthNoAuth)) 169 | }) 170 | }) 171 | }) 172 | -------------------------------------------------------------------------------- /parsec/test/list_authenticators.json: -------------------------------------------------------------------------------- 1 | { 2 | "op_code": 14, 3 | "tests": [ 4 | { 5 | "name": "normal_response", 6 | "request_data": {}, 7 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAA", 8 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAA8AAAAAAA4AAAAAAAAACg0KB05vIEF1dGgYASAt", 9 | "expected_response": [ 10 | { 11 | "description": "No Auth", 12 | "id": 0, 13 | "version_maj": 0, 14 | "version_min": 1, 15 | "version_rev": 45 16 | } 17 | ], 18 | "expect_success": true 19 | }, 20 | { 21 | "name": "failing response", 22 | "request_data": {}, 23 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAA", 24 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAAAAAAAAAA4AAABuBAAA", 25 | "expected_response": [], 26 | "expect_success": false 27 | }, 28 | { 29 | "name": "auth_direct", 30 | "request_data": {}, 31 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAA", 32 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAABAAAAAAAA4AAAAAAAAACg4KBmRpcmVjdBABGAEoAQ==", 33 | "expected_response": [ 34 | { 35 | "description": "direct", 36 | "id": 1, 37 | "version_maj": 1, 38 | "version_min": 1, 39 | "version_rev": 0 40 | } 41 | ], 42 | "expect_success": true 43 | }, 44 | { 45 | "name": "auth_direct,unix", 46 | "request_data": {}, 47 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAA", 48 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAB4AAAAAAA4AAAAAAAAACg4KBmRpcmVjdBABGAEoAQoMCgR1bml4EAEYASgD", 49 | "expected_response": [ 50 | { 51 | "description": "direct", 52 | "id": 1, 53 | "version_maj": 1, 54 | "version_min": 1, 55 | "version_rev": 0 56 | }, 57 | { 58 | "description": "unix", 59 | "id": 3, 60 | "version_maj": 1, 61 | "version_min": 1, 62 | "version_rev": 0 63 | } 64 | ], 65 | "expect_success": true 66 | }, 67 | { 68 | "name": "auth_unix,direct", 69 | "request_data": {}, 70 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAA", 71 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAB4AAAAAAA4AAAAAAAAACgwKBHVuaXgQARgBKAMKDgoGZGlyZWN0EAEYASgB", 72 | "expected_response": [ 73 | { 74 | "description": "unix", 75 | "id": 3, 76 | "version_maj": 1, 77 | "version_min": 1, 78 | "version_rev": 0 79 | }, 80 | { 81 | "description": "direct", 82 | "id": 1, 83 | "version_maj": 1, 84 | "version_min": 1, 85 | "version_rev": 0 86 | } 87 | ], 88 | "expect_success": true 89 | }, 90 | { 91 | "name": "auth_unix", 92 | "request_data": {}, 93 | "expected_request_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAA", 94 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAA4AAAAAAA4AAAAAAAAACgwKBHVuaXgQARgBKAM=", 95 | "expected_response": [ 96 | { 97 | "description": "unix", 98 | "id": 3, 99 | "version_maj": 1, 100 | "version_min": 1, 101 | "version_rev": 0 102 | } 103 | ], 104 | "expect_success": true 105 | }, 106 | { 107 | "name": "auth_jwt,direct", 108 | "request_data": {}, 109 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAA", 110 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAB0AAAAAAA4AAAAAAAAACgsKA2p3dBABGAEoAgoOCgZkaXJlY3QQARgBKAE=", 111 | "expected_response": [ 112 | { 113 | "description": "jwt", 114 | "id": 2, 115 | "version_maj": 1, 116 | "version_min": 1, 117 | "version_rev": 0 118 | }, 119 | { 120 | "description": "direct", 121 | "id": 1, 122 | "version_maj": 1, 123 | "version_min": 1, 124 | "version_rev": 0 125 | } 126 | ], 127 | "expect_success": true 128 | } 129 | ] 130 | } -------------------------------------------------------------------------------- /parsec/test/list_providers.json: -------------------------------------------------------------------------------- 1 | { 2 | "op_code": 8, 3 | "tests": [ 4 | { 5 | "name": "normal_response", 6 | "request_data": {}, 7 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA", 8 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAIYAAAAAAAgAAAAAAAAACkMKJDdiMzQ0ZGU2LTY5YzMtNGMxYy05MWNlLTVjYjQ5OTgyMDViOBILbWJlZCBjcnlwdG8aBnZlbmRvciABKA0wFzgBCj8KJDlhYzUyYmU4LTRiOWMtNGQyMC05YTZmLWEyZDU2ZjQ0NzQ2NBIDdHBtGgp0cG0gdmVuZG9yIAIoKzADOAM=", 9 | "expected_response": [ 10 | { 11 | "description": "mbed crypto", 12 | "id": 1, 13 | "uuid": "7b344de6-69c3-4c1c-91ce-5cb4998205b8", 14 | "vendor": "vendor", 15 | "version_maj": 1, 16 | "version_min": 13, 17 | "version_rev": 23 18 | }, 19 | { 20 | "description": "tpm", 21 | "id": 3, 22 | "uuid": "9ac52be8-4b9c-4d20-9a6f-a2d56f447464", 23 | "vendor": "tpm vendor", 24 | "version_maj": 2, 25 | "version_min": 43, 26 | "version_rev": 3 27 | } 28 | ], 29 | "expect_success": true 30 | }, 31 | { 32 | "name": "fail response", 33 | "request_data": {}, 34 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA", 35 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAgAAAALAAAA", 36 | "expected_response": [], 37 | "expect_success": false 38 | }, 39 | { 40 | "name": "provider_mbed", 41 | "request_data": {}, 42 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA", 43 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAEUAAAAAAAgAAAAAAAAACkMKJDdiMzQ0ZGU2LTY5YzMtNGMxYy05MWNlLTVjYjQ5OTgyMDViOBILbWJlZCBjcnlwdG8aBnZlbmRvciABKA0wFzgB", 44 | "expected_response": [ 45 | { 46 | "description": "mbed crypto", 47 | "id": 1, 48 | "uuid": "7b344de6-69c3-4c1c-91ce-5cb4998205b8", 49 | "vendor": "vendor", 50 | "version_maj": 1, 51 | "version_min": 13, 52 | "version_rev": 23 53 | } 54 | ], 55 | "expect_success": true 56 | }, 57 | { 58 | "name": "provider_tpm,mbed", 59 | "request_data": {}, 60 | "expected_request_binary": "EKfAXh4AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA", 61 | "response_binary": "EKfAXh4AAQAAAAEAAAAAAAAAAAAAAIIAAAAAAAgAAAAAAAAACjsKJDdiMzQ0ZGU2LTY5YzMtNGMxYy05MWNlLTVjYjQ5OTgyMDViOBIDdHBtGgZ2ZW5kb3IgASgNMBc4AwpDCiQ3YjM0NGRlNi02OWMzLTRjMWMtOTFjZS01Y2I0OTk4MjA1YjgSC21iZWQgY3J5cHRvGgZ2ZW5kb3IgASgNMBc4AQ==", 62 | "expected_response": [ 63 | { 64 | "description": "tpm", 65 | "id": 3, 66 | "uuid": "7b344de6-69c3-4c1c-91ce-5cb4998205b8", 67 | "vendor": "vendor", 68 | "version_maj": 1, 69 | "version_min": 13, 70 | "version_rev": 23 71 | }, 72 | { 73 | "description": "mbed crypto", 74 | "id": 1, 75 | "uuid": "7b344de6-69c3-4c1c-91ce-5cb4998205b8", 76 | "vendor": "vendor", 77 | "version_maj": 1, 78 | "version_min": 13, 79 | "version_rev": 23 80 | } 81 | ], 82 | "expect_success": true 83 | } 84 | ] 85 | } -------------------------------------------------------------------------------- /parsec/test/mocktests/contstants_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | const mockServerRoot = "../../../mock-test/parsec-mock" 4 | const mockServerPath = mockServerRoot + "/parsec_mock/parsec_mock.py" 5 | const mockServerData = mockServerRoot + "/generator_output" 6 | const parsecSocket = "/tmp/parsec.sock" 7 | -------------------------------------------------------------------------------- /parsec/test/mocktests/create_configured_client_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/parallaxsecond/parsec-client-go/parsec" 7 | ) 8 | 9 | var _ = Describe("create configured basic client", func() { 10 | var ( 11 | server *mockServer 12 | err error 13 | ) 14 | BeforeEach(func() { 15 | server, err = startMockServer() 16 | Expect(err).NotTo(HaveOccurred()) 17 | }) 18 | 19 | It("Should create and configure with no errors", func() { 20 | var basicClient *parsec.BasicClient 21 | basicClient, err = parsec.CreateConfiguredClient("admin_priv") 22 | Expect(err).NotTo(HaveOccurred()) 23 | defer basicClient.Close() 24 | Expect(basicClient.GetAuthenticatorType()).To(Equal(parsec.AuthDirect)) 25 | Expect(basicClient.GetImplicitProvider()).To(Equal(parsec.ProviderPKCS11)) 26 | }) 27 | 28 | AfterEach(func() { 29 | server.stop() 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /parsec/test/mocktests/delete_client_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/parallaxsecond/parsec-client-go/interface/requests" 7 | "github.com/parallaxsecond/parsec-client-go/parsec" 8 | ) 9 | 10 | var _ = Describe("delete client", func() { 11 | var ( 12 | server *mockServer 13 | err error 14 | ) 15 | BeforeEach(func() { 16 | server, err = startMockServer() 17 | Expect(err).NotTo(HaveOccurred()) 18 | }) 19 | 20 | Context("With direct auth admin_priv", func() { 21 | Context("delete exiting client", func() { 22 | It("Should should give us no error", func() { 23 | var basicClient *parsec.BasicClient 24 | basicClient, err = parsec.CreateConfiguredClient("admin_priv") 25 | Expect(err).NotTo(HaveOccurred()) 26 | defer basicClient.Close() 27 | err = basicClient.DeleteClient("existing client") 28 | Expect(err).NotTo(HaveOccurred()) 29 | }) 30 | }) 31 | Context("with non existing client", func() { 32 | It("Should should error", func() { 33 | var basicClient *parsec.BasicClient 34 | basicClient, err = parsec.CreateConfiguredClient("admin_priv") 35 | Expect(err).NotTo(HaveOccurred()) 36 | defer basicClient.Close() 37 | err = basicClient.DeleteClient("not exist") 38 | Expect(err).To(HaveOccurred()) 39 | Expect(err.Error()).To(Equal(requests.StatusPsaErrorDoesNotExist.ToErr().Error())) 40 | }) 41 | 42 | }) 43 | }) 44 | Context("With direct auth no_admin", func() { 45 | It("Should error when listing clients", func() { 46 | var basicClient *parsec.BasicClient 47 | basicClient, err = parsec.CreateConfiguredClient("no_admin") 48 | Expect(err).NotTo(HaveOccurred()) 49 | defer basicClient.Close() 50 | err = basicClient.DeleteClient("client exists") 51 | Expect(err).To(HaveOccurred()) 52 | Expect(err.Error()).To(Equal(requests.StatusAdminOperation.ToErr().Error())) 53 | }) 54 | 55 | }) 56 | 57 | AfterEach(func() { 58 | server.stop() 59 | }) 60 | }) 61 | -------------------------------------------------------------------------------- /parsec/test/mocktests/list_authenticators_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/parallaxsecond/parsec-client-go/parsec" 7 | ) 8 | 9 | var _ = Describe("list authenticators", func() { 10 | var ( 11 | server *mockServer 12 | err error 13 | ) 14 | BeforeEach(func() { 15 | server, err = startMockServer() 16 | Expect(err).NotTo(HaveOccurred()) 17 | }) 18 | 19 | Context("With no provider", func() { 20 | It("Should give us one provider", func() { 21 | var basicClient *parsec.BasicClient 22 | basicClient, err = parsec.CreateNakedClient() 23 | Expect(err).NotTo(HaveOccurred()) 24 | defer basicClient.Close() 25 | var authInfo []*parsec.AuthenticatorInfo 26 | authInfo, err = basicClient.ListAuthenticators() 27 | Expect(err).NotTo(HaveOccurred()) 28 | Expect(len(authInfo)).To(Equal(1)) 29 | Expect(authInfo[0].Description).To(Equal("direct auth")) 30 | }) 31 | }) 32 | 33 | AfterEach(func() { 34 | server.stop() 35 | }) 36 | }) 37 | -------------------------------------------------------------------------------- /parsec/test/mocktests/list_clients_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/parallaxsecond/parsec-client-go/parsec" 7 | ) 8 | 9 | var _ = Describe("list clients", func() { 10 | var ( 11 | server *mockServer 12 | err error 13 | ) 14 | BeforeEach(func() { 15 | server, err = startMockServer() 16 | Expect(err).NotTo(HaveOccurred()) 17 | }) 18 | 19 | Context("With direct auth admin_priv", func() { 20 | It("Should give us two clients", func() { 21 | var basicClient *parsec.BasicClient 22 | basicClient, err = parsec.CreateConfiguredClient("admin_priv") 23 | Expect(err).NotTo(HaveOccurred()) 24 | defer basicClient.Close() 25 | var clients []string 26 | clients, err = basicClient.ListClients() 27 | Expect(err).NotTo(HaveOccurred()) 28 | Expect(len(clients)).To(Equal(2)) 29 | Expect(clients).To(Equal([]string{"jim", "bob"})) 30 | }) 31 | }) 32 | Context("With direct auth no_admin", func() { 33 | It("Should error when listing clients", func() { 34 | var basicClient *parsec.BasicClient 35 | basicClient, err = parsec.CreateConfiguredClient("no_admin") 36 | Expect(err).NotTo(HaveOccurred()) 37 | defer basicClient.Close() 38 | var clients []string 39 | clients, err = basicClient.ListClients() 40 | Expect(err).To(HaveOccurred()) 41 | Expect(err.Error()).To(Equal("the operation requires admin privilege")) 42 | Expect(clients).To(BeNil()) 43 | }) 44 | 45 | }) 46 | 47 | AfterEach(func() { 48 | server.stop() 49 | }) 50 | }) 51 | -------------------------------------------------------------------------------- /parsec/test/mocktests/list_providers_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | "github.com/parallaxsecond/parsec-client-go/parsec" 7 | ) 8 | 9 | var _ = Describe("list providers", func() { 10 | var ( 11 | server *mockServer 12 | err error 13 | ) 14 | BeforeEach(func() { 15 | server, err = startMockServer() 16 | Expect(err).NotTo(HaveOccurred()) 17 | }) 18 | 19 | Context("With no provider", func() { 20 | It("Should give us one provider", func() { 21 | var basicClient *parsec.BasicClient 22 | basicClient, err = parsec.CreateNakedClient() 23 | Expect(err).NotTo(HaveOccurred()) 24 | defer basicClient.Close() 25 | var provInfo []*parsec.ProviderInfo 26 | provInfo, err = basicClient.ListProviders() 27 | Expect(err).NotTo(HaveOccurred()) 28 | Expect(len(provInfo)).To(Equal(1)) 29 | Expect(provInfo[0].Description).To(Equal("Some empty provider")) 30 | }) 31 | }) 32 | 33 | AfterEach(func() { 34 | server.stop() 35 | }) 36 | }) 37 | -------------------------------------------------------------------------------- /parsec/test/mocktests/main_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestRequests(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "requests package internal suite") 13 | } 14 | -------------------------------------------------------------------------------- /parsec/test/mocktests/mock_server_test.go: -------------------------------------------------------------------------------- 1 | package mocktests_test 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "fmt" 7 | "os" 8 | "os/exec" 9 | "time" 10 | 11 | "github.com/onsi/ginkgo" 12 | ) 13 | 14 | type mockServer struct { 15 | cancel context.CancelFunc 16 | } 17 | 18 | func startMockServer() (*mockServer, error) { 19 | os.Setenv("PARSEC_SERVICE_ENDPOINT", "unix:"+parsecSocket) 20 | var pythonExe string 21 | pythonExe, err := exec.LookPath("python3") 22 | if err != nil { 23 | return nil, err 24 | } 25 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 26 | cmdRunMock := exec.CommandContext(ctx, pythonExe, mockServerPath, "--test-folder", mockServerData, "--parsec-socket", parsecSocket) 27 | cmdRunMock.Stdout = ginkgo.GinkgoWriter 28 | cmdRunMock.Stderr = ginkgo.GinkgoWriter 29 | 30 | fmt.Fprintf(ginkgo.GinkgoWriter, "Running: %s\n", cmdRunMock.String()) 31 | err = cmdRunMock.Start() 32 | if err != nil { 33 | cancel() 34 | return nil, err 35 | } 36 | 37 | ms := &mockServer{ 38 | cancel: cancel, 39 | } 40 | err = waitForServerSocket() 41 | if err != nil { 42 | cancel() 43 | return nil, err 44 | } 45 | return ms, nil 46 | } 47 | 48 | func waitForServerSocket() error { 49 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) 50 | defer cancel() 51 | for { 52 | if _, err := os.Stat(parsecSocket); err == nil { 53 | // parsec socket exists, exit 54 | fmt.Fprintf(ginkgo.GinkgoWriter, "found parsec socket\n") 55 | // need short wait till socket can connect 56 | time.Sleep(200 * time.Millisecond) 57 | return nil 58 | } else if errors.Is(err, os.ErrNotExist) { 59 | // do nothing, wait a bit or timeout 60 | select { 61 | case <-ctx.Done(): 62 | fmt.Fprintf(ginkgo.GinkgoWriter, "Context done") 63 | return ctx.Err() 64 | case <-time.After(10 * time.Microsecond): 65 | continue 66 | } 67 | } else { 68 | fmt.Fprintf(ginkgo.GinkgoWriter, "error statting parsec socket") 69 | return err 70 | } 71 | } 72 | } 73 | 74 | func (ms *mockServer) stop() { 75 | ms.cancel() 76 | } 77 | -------------------------------------------------------------------------------- /parsec/test/mod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Contributors to the Parsec project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | package test 4 | 5 | import ( 6 | "encoding/base64" 7 | "io" 8 | 9 | . "github.com/onsi/ginkgo" //nolint // Using for matching and this is idomatic gomega import 10 | . "github.com/onsi/gomega" //nolint // Using for matching and this is idomatic gomega import 11 | ) 12 | 13 | // testCase contains test data and used for parsing test cases from json file. 14 | type testCase struct { 15 | Name string `json:"name"` 16 | Request string `json:"expected_request_binary"` 17 | Response string `json:"response_binary"` 18 | } 19 | 20 | // Implements the Connection interface to allow us to check and inject data during tests 21 | type mockConnection struct { 22 | responseLookup map[string]string // key = base64 encoded request, value = base64 encoded response 23 | nextResponse *string // copied in if we find a matching request on write - will be read in read then cleared 24 | } 25 | 26 | func newMockConnection() *mockConnection { 27 | return &mockConnection{ 28 | responseLookup: make(map[string]string), 29 | nextResponse: nil, 30 | } 31 | } 32 | 33 | func newMockConnectionFromTestCase(testCases []testCase) *mockConnection { 34 | mc := newMockConnection() 35 | for _, tc := range testCases { 36 | mc.responseLookup[tc.Request] = tc.Response 37 | } 38 | return mc 39 | } 40 | 41 | func (m *mockConnection) Open() error { 42 | m.nextResponse = nil 43 | return nil 44 | } 45 | 46 | func (m *mockConnection) Read(p []byte) (n int, err error) { 47 | defer func() { m.nextResponse = nil }() 48 | if m.nextResponse == nil { 49 | return 0, io.EOF 50 | } 51 | 52 | resp, err := base64.StdEncoding.DecodeString(*m.nextResponse) 53 | if err != nil { 54 | panic(err) 55 | } 56 | 57 | return copy(p, resp), nil 58 | } 59 | 60 | func (m *mockConnection) Write(p []byte) (n int, err error) { 61 | encodedOutput := base64.StdEncoding.EncodeToString(p) 62 | if resp, ok := m.responseLookup[encodedOutput]; ok { 63 | m.nextResponse = &resp 64 | } 65 | Expect(m.nextResponse).NotTo(BeNil()) 66 | return len(p), nil 67 | } 68 | 69 | func (m *mockConnection) Close() error { 70 | return nil 71 | } 72 | 73 | // Implements the Connection interface to allow us to check no reads or writes have taken place 74 | type noopConnection struct { 75 | } 76 | 77 | func newNoopConnection() *noopConnection { 78 | return &noopConnection{} 79 | } 80 | 81 | func (m *noopConnection) Open() error { 82 | Fail("Should not have been called") 83 | return nil 84 | } 85 | 86 | func (m *noopConnection) Read(p []byte) (n int, err error) { 87 | Fail("Should not have been called") 88 | return 0, nil 89 | } 90 | 91 | func (m *noopConnection) Write(p []byte) (n int, err error) { 92 | Fail("Should not have been called") 93 | return 0, nil 94 | } 95 | 96 | func (m *noopConnection) Close() error { 97 | Fail("Should not have been called") 98 | return nil 99 | } 100 | --------------------------------------------------------------------------------