├── .github ├── dependabot.yml └── workflows │ ├── a10rest-docker-image.yml │ ├── android.yml │ └── codeql-analysis.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── configs-docker ├── config.yaml ├── mosquitto.conf └── sgx_default_qcnl.conf ├── dist ├── config.yaml ├── ga10.service ├── make_distribution.sh ├── ta10.service ├── temporary.crt └── temporary.key ├── docker-compose.yml ├── docs ├── automaticStartup.md ├── compiling.md ├── contents.md ├── history.md ├── ignore │ ├── example_EPEV.md │ ├── ga10OldREADME.md │ └── miscstuff.md ├── publications.md ├── running.md └── security.md ├── ga10 ├── .vscode │ └── launch.json ├── Dockerfile ├── config.yaml ├── configuration │ └── configuration.go ├── datalayer │ ├── count.go │ ├── initialisation.go │ ├── internaldbs.go │ ├── mongo.go │ └── mqtt.go ├── enclave.json ├── ga10.go ├── go.mod ├── go.sum ├── logging │ └── logging.go ├── operations │ ├── attestation.go │ ├── claims.go │ ├── elements.go │ ├── expectedValues.go │ ├── log.go │ ├── opaqueobjects.go │ ├── operrors.go │ ├── policies.go │ ├── protocols.go │ ├── results.go │ ├── rules.go │ ├── sessions.go │ ├── signingFunctions.go │ └── verification.go ├── otherconfigfiles │ ├── local.yaml │ └── nconfig.yaml ├── protocols │ ├── a10httprestv2 │ │ └── public.go │ ├── marblerun │ │ └── public.go │ ├── netconfprotocol │ │ └── public.go │ ├── nullprotocol │ │ └── public.go │ ├── registerProtocols.go │ └── testcontainerprotocol │ │ └── public.go ├── rules │ ├── keylime │ │ └── public.go │ ├── marblerun │ │ └── public.go │ ├── nullrule │ │ └── public.go │ ├── registerRules.go │ ├── sysrules │ │ └── public.go │ ├── testcontainerrules │ │ └── public.go │ └── tpm2rules │ │ └── public.go ├── services │ ├── restapi │ │ ├── endpointOpaqueObjects.go │ │ ├── endpointsAttestVerify.go │ │ ├── endpointsClaims.go │ │ ├── endpointsElements.go │ │ ├── endpointsExpectedValues.go │ │ ├── endpointsHealth.go │ │ ├── endpointsLog.go │ │ ├── endpointsPolicies.go │ │ ├── endpointsProtocols.go │ │ ├── endpointsResults.go │ │ ├── endpointsRules.go │ │ ├── endpointsSession.go │ │ ├── initrestapi.go │ │ └── resterrors.go │ ├── webui │ │ ├── attest.go │ │ ├── claims.go │ │ ├── elements.go │ │ ├── expectedvalues.go │ │ ├── homepages.go │ │ ├── initwebapi.go │ │ ├── log.go │ │ ├── opaqueobjects.go │ │ ├── policies.go │ │ ├── protocols.go │ │ ├── results.go │ │ ├── rules.go │ │ ├── sessions.go │ │ ├── templatefunctions.go │ │ └── templates │ │ │ ├── about.html │ │ │ ├── attest.html │ │ │ ├── attestsummary.html │ │ │ ├── base.html │ │ │ ├── claim.html │ │ │ ├── claim_ERROR.html │ │ │ ├── claim_ima.html │ │ │ ├── claim_quote.html │ │ │ ├── claim_tpm2pcrs.html │ │ │ ├── claims.html │ │ │ ├── editelement.html │ │ │ ├── editexpectedvalue.html │ │ │ ├── editpolicy.html │ │ │ ├── element.html │ │ │ ├── elements.html │ │ │ ├── elementsummarylist.html │ │ │ ├── ev.html │ │ │ ├── evs.html │ │ │ ├── evsummarylist.html │ │ │ ├── genericList.html │ │ │ ├── help.html │ │ │ ├── home.html │ │ │ ├── hostinformation.html │ │ │ ├── ima.html │ │ │ ├── log.html │ │ │ ├── opaqueobject.html │ │ │ ├── opaqueobjects.html │ │ │ ├── policies.html │ │ │ ├── policy.html │ │ │ ├── policysummarylist.html │ │ │ ├── protocols.html │ │ │ ├── result.html │ │ │ ├── results.html │ │ │ ├── resultvalue.html │ │ │ ├── rules.html │ │ │ ├── scraps │ │ │ ├── session.html │ │ │ ├── sessions.html │ │ │ ├── tpm2.html │ │ │ ├── tpm2key.html │ │ │ ├── txt.html │ │ │ └── uefi.html │ └── x3270 │ │ ├── initx3270.go │ │ ├── screenrules.go │ │ └── screens.go ├── structures │ ├── claims.go │ ├── common.go │ ├── elements.go │ ├── expectedValues.go │ ├── logs.go │ ├── opaqueobjects.go │ ├── policies.go │ ├── protocols.go │ ├── results.go │ ├── rules.go │ ├── sessions.go │ └── types.go ├── temporary.crt ├── temporary.key ├── tests │ ├── exampledatabase │ │ ├── elements.json │ │ ├── expectedvalues.json │ │ └── policies.json │ ├── p11test │ │ ├── p.go │ │ └── yubihsm_pkcs11.conf │ ├── pkcs11test │ │ ├── go.mod │ │ ├── go.sum │ │ ├── p.go │ │ └── yubihsm_pkcs11.conf │ └── testscripts │ │ ├── attest.sh │ │ ├── get.sh │ │ ├── verify_laptop.sh │ │ └── verify_pi.sh └── utilities │ ├── hashes.go │ ├── identifiers.go │ ├── timestamps.go │ └── tpm.go ├── scripts ├── att.sh └── attAutomation │ ├── CreateElements.sh │ ├── GenerateKeys.sh │ ├── README.txt │ ├── VerifyElements.sh │ ├── attest.py │ ├── closeSession.py │ ├── createElement.py │ ├── createExpected.py │ ├── createKeys.py │ ├── createSession.py │ ├── elements.txt │ ├── ga10pythonlib.py │ └── verify.py └── ta10 ├── common ├── identifiers.go └── unsafemode.go ├── go.mod ├── go.sum ├── ima └── endpoints.go ├── sys └── endpoints.go ├── ta10.go ├── tpm2 ├── endpointstpm2.go ├── opentpm_unix.go └── opentpm_windows.go └── uefi └── endpoints.go /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/a10rest-docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Build the Docker image 18 | run: docker build --file a10rest/Dockerfile.local --tag a10rest:$(date +%s) --output type=local,dest=a10rest.build.output . 19 | - uses: slsa-framework/github-actions-demo@v0.1 20 | with: 21 | artifact_path: a10rest.build.output 22 | output_path: a10rest.provenance 23 | continue-on-error: true 24 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: set up JDK 11 16 | uses: actions/setup-java@v2 17 | with: 18 | java-version: "11" 19 | distribution: "adopt" 20 | cache: gradle 21 | - name: Grant execute permission for gradlew 22 | working-directory: ./apps/mobileattester 23 | run: chmod +x gradlew 24 | 25 | - name: Run lint 26 | working-directory: ./apps/mobileattester 27 | run: ./gradlew lintDebug 28 | - name: Upload html test report 29 | uses: actions/upload-artifact@v2 30 | with: 31 | name: lint.html 32 | path: ./apps/mobileattester/app/build/reports/lint-results-debug.html 33 | 34 | - name: Build with Gradle 35 | working-directory: ./apps/mobileattester 36 | run: ./gradlew build 37 | 38 | test: 39 | needs: [build] 40 | name: Run Unit Tests 41 | runs-on: ubuntu-latest 42 | steps: 43 | - uses: actions/checkout@v2 44 | - name: set up JDK 11 45 | uses: actions/setup-java@v2 46 | with: 47 | java-version: "11" 48 | distribution: "adopt" 49 | cache: gradle 50 | - name: Run unit tests 51 | working-directory: ./apps/mobileattester 52 | run: bash ./gradlew test --stacktrace 53 | 54 | apk: 55 | needs: [test] 56 | name: Generate APK 57 | runs-on: ubuntu-latest 58 | steps: 59 | - name: Checkout 60 | uses: actions/checkout@v2 61 | - name: set up JDK 1.8 62 | uses: actions/setup-java@v1 63 | with: 64 | java-version: 11 65 | - name: Grant execute permission for gradlew 66 | working-directory: ./apps/mobileattester 67 | run: chmod +x gradlew 68 | - name: Build APK 69 | working-directory: ./apps/mobileattester 70 | run: ./gradlew assembleDebug 71 | - name: Upload APK 72 | uses: actions/upload-artifact@v2 73 | with: 74 | name: app 75 | path: ./apps/mobileattester/app/build/outputs/apk/debug/app-debug.apk 76 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '33 14 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'go', 'javascript', 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v2 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v1 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v1 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v1 71 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome 2 | 3 | Welcome to the Nokia Attestation Engine. See the README.md for more information and INSTALL.md here in the root directory for how to install using docker. In the u10 and a10rest directories you'll find the README.md files there on how to start the components without docker. 4 | 5 | In the A10 directory you'll find the installation instructions for building the python libraries and how to deploy these locally. 6 | 7 | # Submitting Changes 8 | 9 | Fork, make a pull request, push and notify me 10 | 11 | # Bugs, Enhancements and Missing Features 12 | 13 | There are lots of these. Use the issue tracker on github. 14 | 15 | I can't promise all features will be implemented nor all bugs fixed, but there are quite a few places where things could be improvied. 16 | 17 | Please remember that this software was build to explore ideas so things such as security, logins etc where not considered. 18 | 19 | # Thanks 20 | 21 | Huge thanks to anyone who provides feedback! 22 | 23 | # Getting Help 24 | 25 | Github issue tracker would be the best place - We'll be reading this fairly often. If things need more discussion then we can move to email on a case-by-case basis. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Clear BSD License 2 | 3 | Copyright (c) 2021 Nokia 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted (subject to the limitations in the disclaimer 8 | below) provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from this 19 | software without specific prior written permission. 20 | 21 | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY 22 | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 23 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 30 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A10 - Nokia Attestation Engine 2 | 3 | This is the source for the Nokia Attestation Engine A10. 4 | 5 | This software is used as the remote attestation engine as part of a trusted and/or confidential computing environment. This is the system that holds the known good values about devices and other elements, and provides the attestation and validation mechanisms. 6 | 7 | The software here is provided as-is - there is no security (http for the win!) and the error checking in places is completely missing. The point of this was to explore more interesting mechanisms for remote attestation and to implement ideas from the IEFT RATS specification. *READ* the security section!!! 8 | 9 | Refer to the [contents](docs/contents.md) in the `docs` directory. -------------------------------------------------------------------------------- /configs-docker/config.yaml: -------------------------------------------------------------------------------- 1 | #Some general naming 2 | system: 3 | name: ASVR_GO_1 4 | 5 | #MongoDB Configuration 6 | database: 7 | connection: mongodb://mongodb:27017 8 | name: testasvrlocal 9 | 10 | #MQTT Configuration 11 | messaging: 12 | broker: messagebus 13 | port: 1883 14 | clientid: asvrgo1 15 | 16 | #REST Interface Configuration 17 | rest: 18 | port: 8520 19 | crt: temporary.crt 20 | key: temporary.key 21 | usehttp: false 22 | 23 | #Web Interface Configuration 24 | web: 25 | port: 8540 26 | crt: temporary.crt 27 | key: temporary.key 28 | usehttp: true 29 | 30 | 31 | #Web Interface Configuration 32 | x3270: 33 | port: 3270 34 | 35 | 36 | #Log file 37 | logging: 38 | logfilelocation: /tmp/ga10.log 39 | sessionupdatelogging: false 40 | 41 | #Keylime 42 | keylime: 43 | apiurl: "http://keylime:8080" -------------------------------------------------------------------------------- /configs-docker/mosquitto.conf: -------------------------------------------------------------------------------- 1 | listener 1883 2 | allow_anonymous true 3 | -------------------------------------------------------------------------------- /dist/config.yaml: -------------------------------------------------------------------------------- 1 | #Some general naming 2 | system: 3 | name: ASVR_GO_1 4 | 5 | #MongoDB Configuration 6 | database: 7 | connection: mongodb://192.168.1.203:27017 8 | name: test1 9 | 10 | #MQTT Configuration 11 | messaging: 12 | broker: 192.168.1.203 13 | port: 1883 14 | clientid: asvrgo1 15 | 16 | #REST Interface Configuration 17 | rest: 18 | port: 8520 19 | crt: temporary.crt 20 | key: temporary.key 21 | usehttp: false 22 | 23 | #Web Interface Configuration 24 | web: 25 | port: 8540 26 | crt: temporary.crt 27 | key: temporary.key 28 | usehttp: true 29 | 30 | #x3270 Configuraiton 31 | x3270: 32 | port: 3270 33 | 34 | #D10 Service Configuration 35 | d10: 36 | port: 8521 37 | files: /var/ga10/d10 38 | 39 | #Log file 40 | logging: 41 | logfilelocation: /tmp/ga10.log 42 | sessionupdatelogging: false 43 | -------------------------------------------------------------------------------- /dist/ga10.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=GA10 Attestation Engine 3 | After=network.target 4 | StartLimitIntervalSec=0 5 | 6 | [Service] 7 | Type=simple 8 | Restart=always 9 | RestartSec=1 10 | User=ian 11 | ExecStart=/opt/nae/ga10 -config=/opt/nae/ga10config.yaml 12 | 13 | [Install] 14 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /dist/make_distribution.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash +x 2 | 3 | echo "Making distribution binaries" 4 | 5 | DISTDIR=/tmp 6 | GA10_BINARY_NAME=ga10 7 | TA10_BINARY_NAME=ta10 8 | 9 | DATE=`date +%s%3N` 10 | LD_RELEASE_FLAGS="-X main.BUILD=$DATE" 11 | 12 | echo "Binary release code is " $DATE 13 | 14 | echo "Making ga10" 15 | 16 | cd ../ga10 17 | go get -u 18 | go mod tidy 19 | 20 | GOOS=linux GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_linuxamd64 ga10.go 21 | GOOS=linux GOARCH=arm64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_linuxarm64 ga10.go 22 | GOOS=linux GOARCH=arm go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_linuxarm32 ga10.go 23 | 24 | GOOS=illumos GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_illumosamd64 ga10.go 25 | GOOS=windows GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_windowsamd64 ga10.go 26 | GOOS=openbsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_openBSDamd64 ga10.go 27 | GOOS=freebsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_freeBSDamd64 ga10.go 28 | 29 | cd ../ta10 30 | go get -u 31 | go mod tidy 32 | 33 | GOOS=linux GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_linuxamd64 ta10.go 34 | GOOS=linux GOARCH=arm64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_linuxarm64 ta10.go 35 | GOOS=linux GOARCH=arm go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_linuxarm32 ta10.go 36 | 37 | GOOS=illumos GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_illumosamd64 ta10.go 38 | GOOS=windows GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_windowsamd64 ta10.go 39 | GOOS=openbsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_openBSDamd64 ta10.go 40 | GOOS=freebsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_freeBSDamd64 ta10.go 41 | 42 | echo "Listing binaries" 43 | 44 | cd $DISTDIR 45 | ls -l ga10_* ta10_* 46 | 47 | echo "SHA256 Values" 48 | 49 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_linuxamd64 50 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_linuxarm64 51 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_linuxarm32 52 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_illumosamd64 53 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_windowsamd64 54 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_openBSDamd64 55 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_freeBSDamd64 56 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_linuxamd64 57 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_linuxarm64 58 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_linuxarm32 59 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_illumosamd64 60 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_windowsamd64 61 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_openBSDamd64 62 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_freeBSDamd64 63 | 64 | 65 | echo "Done." -------------------------------------------------------------------------------- /dist/ta10.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=TA10 Trust Agent 3 | After=network.target 4 | StartLimitIntervalSec=0 5 | 6 | [Service] 7 | Type=simple 8 | Restart=always 9 | RestartSec=1 10 | User=root 11 | ExecStart=/opt/nae/ta10 12 | 13 | [Install] 14 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /dist/temporary.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID+TCCAuGgAwIBAgIUVJZap9c3I9vnPWzjuCdr2HzMn58wDQYJKoZIhvcNAQEL 3 | BQAwgYsxCzAJBgNVBAYTAkZJMRAwDgYDVQQIDAdVdXNpbWFhMQ4wDAYDVQQHDAVT 4 | aXBvbzESMBAGA1UECgwJQ2VmZnlsT3BpMQwwCgYDVQQLDANSJkQxDDAKBgNVBAMM 5 | A0lhbjEqMCgGCSqGSIb3DQEJARYbaWFuLmp1c3Rpbi5vbGl2ZXJAZ21haWwuY29t 6 | MB4XDTIzMDQyNDE2NDEyM1oXDTI0MDQyMzE2NDEyM1owgYsxCzAJBgNVBAYTAkZJ 7 | MRAwDgYDVQQIDAdVdXNpbWFhMQ4wDAYDVQQHDAVTaXBvbzESMBAGA1UECgwJQ2Vm 8 | ZnlsT3BpMQwwCgYDVQQLDANSJkQxDDAKBgNVBAMMA0lhbjEqMCgGCSqGSIb3DQEJ 9 | ARYbaWFuLmp1c3Rpbi5vbGl2ZXJAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEF 10 | AAOCAQ8AMIIBCgKCAQEAnYeTyopKf82aGAtACj3GFXBDyAqnOWz3t5P8x7mhU6TW 11 | /+RKbKIpV9/Gytg0hQOsXf5izjOqwu92RJA08W0iO6J/GNFEuYg3tf3MYtFmDZL7 12 | DtHicRY+apSgrv4NtpTezW0DHFdyLHK0RL32Fgkb9JRHfQdssRmymKu8PvPxyFw7 13 | HbD7MurORiGycl/oVdrRhws7lMF/kLuK+ksh3G6M/+sF/4HCtAJ37aeXRAnudktB 14 | RelkBd80HKebsbtPkwJrF1g5VpVBDgJVx28MfRrGLotiKwmAp1nVha6JcGZ6y3Sl 15 | BYTW96/g1QlxOC7tYef0QyyGDeAhIivSwlzuGZ3EzQIDAQABo1MwUTAdBgNVHQ4E 16 | FgQUhMNzN/omyGgTvG5jqDWtFN1G/lkwHwYDVR0jBBgwFoAUhMNzN/omyGgTvG5j 17 | qDWtFN1G/lkwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAmB24 18 | b+ST3ds4pfdiAB6Xfenkk3Fo9cg4hDA9v1nQvXe49x9ZMq5yZ9tkOIWtI0y2nCky 19 | qUGbU08EuZmLyq7ReurRg2nMLi/M+xMJmaCzMMg8vQPMwcAy/EsDgVUS66rbWMYn 20 | VA/zLbjkNAXPzxYzVTSKVdw4loNLagoOkCZRYotA5w9LlmcC/5yxX9wJxb/K7CD7 21 | HPovpR1alU2J5vAbjmo/TAjRFzkt2pQ8kqjAmdWjJb/zIJWwv/s62obb/Ye9kZy4 22 | 40CejuNxsYIvkMyeNAAs6psDO/eEMQITvtaMakczM6qQpdX6yYdWnUOvvjOfu6YA 23 | k7nQ2CE2vEAiLhxZIQ== 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /dist/temporary.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdh5PKikp/zZoY 3 | C0AKPcYVcEPICqc5bPe3k/zHuaFTpNb/5EpsoilX38bK2DSFA6xd/mLOM6rC73ZE 4 | kDTxbSI7on8Y0US5iDe1/cxi0WYNkvsO0eJxFj5qlKCu/g22lN7NbQMcV3IscrRE 5 | vfYWCRv0lEd9B2yxGbKYq7w+8/HIXDsdsPsy6s5GIbJyX+hV2tGHCzuUwX+Qu4r6 6 | SyHcboz/6wX/gcK0Anftp5dECe52S0FF6WQF3zQcp5uxu0+TAmsXWDlWlUEOAlXH 7 | bwx9GsYui2IrCYCnWdWFrolwZnrLdKUFhNb3r+DVCXE4Lu1h5/RDLIYN4CEiK9LC 8 | XO4ZncTNAgMBAAECggEABlx/uNmdyYxtcRQfOWqmMZ5vdkgL2bNPS5AD0LLr01tg 9 | PUQkRz/DKKPGPNG/STHNR5xqtAX9GtMdtQYXxToRfFQDCucEffOEwGon00O+ecTa 10 | M46BNOzfh2FKHdbvidR4LNZ+ninf1/Cn2/DJ27jxco58Vo2ys3IktqqUtvwV4u/a 11 | Tozfc5BWlVd2eYqwv8MyhZPpPxcArC1vPH2os/1/Q/qe8IpCOBHy12SN7Nje+l3p 12 | LYRLHm3rHhKPwHIEd05d5S3BZ0u3Eea20hXAynT2483XaLj1QpImRRZ4O5H0RRRE 13 | apRU7hPlqD8kpD7g6kbkiMCJUOp2Q2NbzfPVH7hlFwKBgQDQKOnABlG5InHPE+su 14 | I1AlvGIThFPbKZEH4MSA3nNEeyqV2P7eRadZexJdF8BAS8yqp73ZbbqFeAkMtL2/ 15 | gc4grOovr4BKy8S3w8utd82dqwD7dUxY+DcP57rogdz7Z82R+RpUwksitv8K1nDM 16 | JGo7WvDUDxQqnRs29WwFb+e9owKBgQDBu9WYeleUwl7krKW9+XmqzDcHwXik6udv 17 | 591IFNbW0B3XGweI18bvTmpYK1cYNYhamloawEiERofX+LVQGKsz33XdcP9a/k7E 18 | ADJy+begSjRvQ7SML3V+KGZSPKE2Wo5ohpBgy+ytFCUb0APC0K/Mk/kjLQHr/ZSg 19 | 5bDp3fG6zwKBgQCoe4T/JN4+v+9oEZI4bOKxOHIVo/SPnmxB+R5zxBl+I0bLtLBN 20 | zgju9xtc+B1mrTOCKXUTqKng39BLVXuDpxflALAoWp+3aojVyIdx51cot8F6xm0+ 21 | UeGXYRO6n2nynwkXjo1Ob1iLR5zU886mnQ7S7f+hVHcZKsJdUHXXTMVAiwKBgDtU 22 | MJdfcA7Ib5MMJD3HdrENlRS09SNcJMAqe6Olbh2e4mSLjIUlv3BtzTdvHl71lepZ 23 | NprWo96OUu+a5LvAsj1Sg5/rCOhu1ORFQy3et5NI5kHktBfyOMMH0D4C/0PL+6ya 24 | +QALs1FVx/96doxkqFG4RyW0lNAWejvD26fjJjIVAoGAeP9pJPFIGFUpUwKTVgsJ 25 | cfm082bJsRpBvRWHhDvJA8nliY1XoTGzoproNxCeZLywkKREflGw2d9AeYgCo8OD 26 | z16VvR/B13l0Dh4fYQS7wGkGEJ2+LcKlEZ+lCWbrFNWHre8vZ9/capxB6PrPn10R 27 | N/cWWNE1DVBVVxu/83lsAk0= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | services: 3 | mongodb: 4 | image: mongo:6-jammy 5 | volumes: 6 | - db:/data/db 7 | messagebus: 8 | image: "eclipse-mosquitto" 9 | volumes: 10 | - ./configs-docker/mosquitto.conf:/mosquitto/config/mosquitto.conf 11 | keylime: 12 | image: keylime_base 13 | environment: 14 | KEYLIME_VERIFIER_MEASURED_BOOT_POLICY_NAME: "example" 15 | entrypoint: ["keylime_validation", "8080"] 16 | ga10: 17 | build: 18 | context: ./ga10 19 | dockerfile: Dockerfile 20 | entrypoint: /ga10 --config=/config.yaml 21 | ports: 22 | - 8520:8520 23 | - 8540:8540 24 | - 3270:3270 25 | volumes: 26 | - ./configs-docker/config.yaml:/config.yaml 27 | - ./ga10/temporary.crt:/temporary.crt 28 | - ./ga10/temporary.key:/temporary.key 29 | - ./configs-docker/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf 30 | volumes: 31 | db: -------------------------------------------------------------------------------- /docs/automaticStartup.md: -------------------------------------------------------------------------------- 1 | # Automatic Startup at Boot 2 | 3 | In this section we present an example distribution for use in a systemd environment. We utilise the file layout given in the follow section. 4 | 5 | ## Example File Layout (Linux/BSD) 6 | 7 | One possible layout is to put everything in `/opt`. Note, `ga10` and `ta10` are put together just for convenience. Set permissions accordingly. 8 | 9 | ```bash 10 | $ pwd 11 | /opt/nae 12 | $ ls -l 13 | total 27364 14 | -rw-rw-r-- 1 ian ian 706 tammi 21 13:01 config.yaml 15 | -rwxrwxr-x 1 ian ian 19448208 tammi 21 13:00 ga10 16 | -rwxrwxr-x 1 ian ian 8554460 tammi 21 13:02 ta10 17 | -rw-rw-r-- 1 ian ian 1440 tammi 21 13:01 temporary.crt 18 | -rw-rw-r-- 1 ian ian 1704 tammi 21 13:01 temporary.key 19 | ``` 20 | 21 | ## GA10 and Systemd on Linux 22 | 23 | Place the following systemd configuration in `/etc/systemd/system` as `ga10.service` 24 | 25 | ``` 26 | [Unit] 27 | Description=GA10 Attestation Engine 28 | After=network.target 29 | StartLimitIntervalSec=0 30 | 31 | [Service] 32 | Type=simple 33 | Restart=always 34 | RestartSec=1 35 | User=ian 36 | ExecStart=/opt/nae/ga10 -config=/opt/nae/config.yaml 37 | 38 | [Install] 39 | WantedBy=multi-user.target 40 | ``` 41 | 42 | Ensure the `config.yaml` is properly configured for your system and installation. 43 | 44 | Start with `systemctl start ga10.service` and enable with `systemctl enable ga10.service`. Use `journalctl -xe` to check startup and possible errors. 45 | 46 | 47 | ## TA10 and Systemd on Linux 48 | 49 | Place the following systemd configuration in `/etc/systemd/system` as `ta10.service` 50 | 51 | Note ta10 may require root to run. Take note of any security aspects. 52 | 53 | ``` 54 | [Unit] 55 | Description=TA10 Trust Agent 56 | After=network.target 57 | StartLimitIntervalSec=0 58 | 59 | [Service] 60 | Type=simple 61 | Restart=always 62 | RestartSec=1 63 | User=root 64 | ExecStart=/opt/nae/ta10 65 | 66 | [Install] 67 | WantedBy=multi-user.target 68 | ``` 69 | 70 | Start with `systemctl start ta10.service` and enable with `systemctl enable ta10.service`. Use `journalctl -xe` to check startup and possible errors. 71 | 72 | ## Windows 73 | 74 | This is possible. In respositor in `dist` is a file `ta10TrustAgent.xml` which provides some hints on this. 75 | 76 | ## BSD (rc.d) 77 | 78 | Yes too. This script placed in `/etc/rc.d` called `ta10` works for startup, at least on my OpenBSD VM: 79 | 80 | ``` 81 | #!/bin/sh 82 | # 83 | # $OpenBSD: ta10 84 | 85 | daemon="/opt/nae/ta10" 86 | 87 | . /etc/rc.d/rc.subr 88 | 89 | rc_cmd $1 90 | ``` -------------------------------------------------------------------------------- /docs/compiling.md: -------------------------------------------------------------------------------- 1 | # Compiling 2 | 3 | Ensure that Go is installed and correctly configured. You will also need the Intel SGX SDK and Edgeless libraries. 4 | 5 | The instructions presented here have been tested in Ubuntu 22.04 om AMD64. 6 | 7 | ## Install SGX SDK and Edgeless 8 | 9 | Intel and Edgeless supply releases for Ubuntu and other operating systems. Here we should for Ubuntu Jammy (22.04). These commands might need to be run as `sudo`. Modify as appropriate for your operating system. 10 | 11 | ```bash 12 | mkdir -p /etc/apt/keyrings 13 | wget -q https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /etc/apt/keyrings/intel-sgx-keyring.asc 14 | echo "deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" > /etc/apt/sources.list.d/intel-sgx.list 15 | apt update 16 | wget https://github.com/edgelesssys/edgelessrt/releases/download/v0.4.1/edgelessrt_0.4.1_amd64_ubuntu-22.04.deb 17 | apt-get install -y ./$ERT_DEB build-essential cmake libssl-dev libsgx-dcap-default-qpl libsgx-dcap-ql libsgx-dcap-quote-verify 18 | ``` 19 | 20 | ## Compiling GA10 21 | 22 | Compilation requires an up-to-date mod file and the Edgeless environment variables - which should be installed if the above went correctly. *MAKE SURE* you are in the `ga10` directory when you run these commands: 23 | 24 | ```bash 25 | go get -u 26 | go mod tidy 27 | . /opt/edgelessrt/share/openenclave/openenclaverc && GOOS=linux GOARCH=amd64 go build -o ga10 28 | ``` 29 | 30 | You will now get a file called `ga10` which is your executable. 31 | 32 | If you wish to reduce the size of the binary, run `strip ga10` 33 | 34 | ## Compiling TA10 35 | 36 | *MAKE SURE* you are in the `ta10` directory. TA10 is much simpler than ga10 and requires just compilation. For your local operating system and architecture you can remove the `GOOS` and `GOARCH` variables, for example as shown below. The `strip` command is optional but it does reduce the binary size a little. 37 | 38 | ```bash 39 | go get -u 40 | go mod tidy 41 | go build -o ta10 42 | strip ta10 43 | ``` 44 | 45 | For other architectures, use `go tool dist list` for a list of operating system and architecture options. Listed below are a few common options - and we like to append this to the binary name when we're generating a few of these for the devices we have (remeber amd64 is 64-bit Intel/AMD x86 based chips, eg: Xeons, i9's, i7's, Threaripper etc etc) 46 | 47 | ```bash 48 | GOOS=linux GOARCH=arm go build -o ta10_arm # eg: Pi 3s 49 | GOOS=linux GOARCH=arm64 go build -o ta10_arm64 # eg: Pi 4, 5s in 64-bit mode (also 3's I think) 50 | GOOS=windows GOARCH=amd64 go build -o ta10_win # eg: Pretty much every Win10, Win11 machine 51 | GOOS=plan9 GOARCH=386 go build -o ta10_belllabs # Because we're Bell Labs.... 52 | GOOS=linux GOARCH=s390x go build -o ta10_mainframe # Because you either have an z-Series in the basement or Hercules 53 | GOOS=solaris GOARCH=amd64 go build -o ta10_solaris # I still mourn the lost of the SparcStation and UltraSparcs, RIP Sun. 54 | GOOS=opebsd GOARCH=amd64 go build -o ta10_openbsd # BSD for security 55 | GOOS=freebsd GOARCH=amd64 go build -o ta10_freeebsd # More BSD fun 56 | GOOS=darmin GOARCH=arm64 go build -o ta10_mac # For the Apple people out there...no TPM, but if you figure out attesting a T2 let me know 57 | GOOS=aix GOARCH=ppc64 go build -o ta10_aix # If you have an AIX box, let me know...DRTM is supported during boot and a TPM too? 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /docs/contents.md: -------------------------------------------------------------------------------- 1 | # Contents 2 | 3 | ## Basics 4 | 5 | * [Compiling](compiling.md) 6 | * [Running](running.md) 7 | * [Automatic Startup](automaticStartup.md) 8 | * [Security and Running in a Producton Environment](security.md) 9 | 10 | ## Getting Started 11 | 12 | * Creating an element 13 | * Attesting and Verification 14 | 15 | ## Structures 16 | 17 | * Elements 18 | * Policies 19 | * Expected Values 20 | * Claims 21 | * Results 22 | * Sessions 23 | 24 | ## Evidence 25 | 26 | * Signing 27 | 28 | ## Protocols and Trust Agents 29 | 30 | * Protocols 31 | * Intents 32 | * Trust Agents and Endpoints 33 | 34 | ## Verification and Rules 35 | 36 | * Rules 37 | 38 | ## Appendicits 39 | 40 | * [History](history.md) 41 | * [Publications](publications.md) -------------------------------------------------------------------------------- /docs/history.md: -------------------------------------------------------------------------------- 1 | # History 2 | 3 | The attestation engine has a long an varied history 4 | 5 | ## A1,A2 and A3 6 | 7 | Early experiments, circle late 2014, early 2015. Written in Javascript with lots of pain regarding reactive, functional programming 8 | 9 | ## A4 10 | 11 | First version that actually worked, also written in Javascript. Not very functional but there existed a trust agent for quoting and quite similar in functionality to systems such as OpenAttestation, Mt.Wilson, Charra and early Keylime. 12 | 13 | ## A5 and A6 14 | 15 | First versions in python 2 and some of the code here ended up in A7. Some parts of A5 and A6 integrated with OpenStack's workflow and workload manager APIs - which worked as long as you didn't update OpenStack as APIs changed randomly betweent versions. 16 | 17 | ## A7 18 | 19 | First properly working attestation server in a very traditional manner (cf: OpenAttestation etc). Written in a mix of python2 and python3. Backend utilised mongodb and assumed the TA talked directly to the tpm2_tools on the client. UI written using python flask. Integrated with OpenStack via a client which was a MITM/hack/kludge to access OpenStack's message bus. This version was demonstrated at ETSI SecurityWeek in 2018 and 2019. Contained a lot of technical debt which made integration hard in some cases. 20 | 21 | ## A8.1 and A8.2 22 | 23 | These were an attempt to write everything in Erlang, and simulaneously in python with threads, proceses and using MQTT for interprocess communication in a complete asynchronous way. I don't think the source coude even exists anymore. 24 | 25 | ## A9 26 | 27 | Was an experiment to use the ELKS analytics stack and the ELKS UI. Was demonstrated in January 2020 for the first time and actively developed for about 6 months until we needed to support new features. Much of this work reappears as plugins and data integration (as attesation apps in A10) into ELKS and ELKS-based tools such as Nokia's NetGuard. 28 | 29 | ## A10 30 | 31 | A much more compliant with IEFT RATS in its data structures. Has a proper protocol backend which takes care of layer 7 and layer 6 of the attestation protocols so we can theoretically support any RoT/auditing system, eg: HSM, UEFI, TPM2.0, TPM1.2 etc, we can even integrate with other attestation engines' trust agents such as KeyLime, OpenAttestation, Go-Attestation etc. Libraries are much better written with a much more consistent API. UI and interfaces are separate components built on top of libraries. The whole thing is designed to integrate with MQTT, logstash, ELKS, whatever AI/ML analytics and the forensics system that is currently under development. Lots of cool features. Supports the notion of *attestation applications** for extensibility making integration with other systems such as Edge/NFV MANO very quick and easy. 32 | 33 | ## GA10 34 | 35 | Even more compliant with IEFT RATS in its data structures and an improved protocol backend which takes care of layer 7 and layer 6 of the attestation protocols. All the cool stuff of A10 but now written in *Go*. Seriously strong typing is so important....Reworked UI, reworked REST API and reworked data structures. Oh so much better. AND, Go has a really nice cross compiler: arm, arm64, i386, amd64, ppc, and then Linux, Windows, Solaris, AIX and Plan 9 from Bell Labs. Also Go makes self-contained binaries so the trust agent is a single binary which makes distribution trivial and the whole server engine itself just needs the binary and the config file :-) 36 | 37 | Includes rules for working with confidential computing structures too. -------------------------------------------------------------------------------- /docs/ignore/ga10OldREADME.md: -------------------------------------------------------------------------------- 1 | To build 2 | 3 | make build 4 | make distribution 5 | make 6 | 7 | go build . 8 | ./a10 --config=config.yaml --runtests=True 9 | 10 | 11 | To run (without build) 12 | 13 | go run . --config=config.yaml --runtests=True 14 | 15 | 16 | To set build version numbers for releases 17 | 18 | go build -ldflags="-X 'main.BUILD=123'" 19 | 20 | with a datetime 21 | 22 | go build -ldflags="-X 'main.BUILD=`date`'" 23 | 24 | 25 | 26 | To generate HTTPS keys 27 | 28 | openssl genrsa 2048 > temporary.key 29 | chmod 400 temporary.key 30 | openssl req -new -x509 -nodes -sha256 -days 365 -key temporary.key -out temporary.crt 31 | 32 | 33 | 34 | 35 | To reduce binary size 36 | 37 | ian@ian-virtual-machine:~/ga10$ go build -ldflags "-w" . 38 | ian@ian-virtual-machine:~/ga10$ ls -l a10 39 | -rwxrwxr-x 1 ian ian 13545955 huhti 25 15:37 a10 40 | ian@ian-virtual-machine:~/ga10$ go build -ldflags "-s -w" . 41 | ian@ian-virtual-machine:~/ga10$ ls -l a10 42 | -rwxrwxr-x 1 ian ian 12517376 huhti 25 15:38 a10 43 | ian@ian-virtual-machine:~/ga10$ 44 | 45 | 46 | Installation 47 | 48 | NB: choose the correct operating system and architecture 49 | 50 | make distribution 51 | cp dist/a10_linuxamd64 /usr/local/bin/a10 52 | cp config.yaml /etc/a10config.yaml 53 | cp a10.service to /etc/systemd/system 54 | 55 | Modify the config.yaml file 56 | 57 | sudo systemctl daemon-reload 58 | sudo systemctl start a10.service 59 | journalctl -xe 60 | 61 | sudo systemctl stop a10.service 62 | 63 | 64 | sudo systemctl enable a10.service 65 | 66 | sudo systemctl disable a10.service 67 | 68 | 69 | 70 | 71 | PKCS#11 72 | 73 | Find the yubihsm.so file 74 | $ ls /usr/lib/x86_64-linux-gnu/pkcs11/ 75 | gnome-keyring-pkcs11.so p11-kit-client.so p11-kit-trust.so yubihsm_pkcs11.so 76 | 77 | github.com/miekg/pkcs11 78 | 79 | Or which ever user can see the YubiHSM (sudo is probably not good) 80 | sudo yubihsm-connector -d 81 | 82 | specify where the yubihsm conf file is 83 | export YUBIHSM_PKCS11_CONF=/home/ian/pkcs11test/yubihsm_pkcs1.conf 84 | -------------------------------------------------------------------------------- /docs/ignore/miscstuff.md: -------------------------------------------------------------------------------- 1 | 2 | To encryption in Go 3 | levelup.gitconnected.com/a-guide-to-rsa-encryption-in-go-1a18d827f35d -------------------------------------------------------------------------------- /docs/security.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | Read carefully: 4 | 5 | * A self-signed key is provided called temporary.key/crt - DO NOT USE THIS IN PRODUCTION OR ANYWHERE. Browsers will complain if you use this. 6 | * THIS IS NOT SECURE!!! 7 | * PUTTING PRIVATE KEYS ON GITHUB FOR ANYTHING ELSE THAN A DEMONSTRATION IS CRAZY. DO NOT DO THIS. 8 | * TO SAVE YOURSELF, SET THE use http FIELDS TO true in the configuration file. 9 | * That isn't secure either... 10 | * GENERATE YOUR OWN KEYS AND KEEP THEM SECURE and use https 11 | * TA10 runs over HTTP !!!! 12 | * DO NOT USE TA10 IN UNSAFE MODE !!! (Even if you're not root!) 13 | * A10 signs claims, results, sessions etc...the keys are randomly generated each him the system is started and aren't recorded anywhere. There is some code to talk PKCS#11 and has been tested with a YubiHSM but it isn't used. Don't rely upon it, I haven't tested it and it is just placeholder at this time. Yes, I'll get arund to writing the proper functionality real soon now...volunteers? 14 | 15 | Now read the section on the use of this software in a production environment. 16 | 17 | # Use in a Production Environment 18 | 19 | Don't. This is not secure and many points where errors and exceptions should be captured are not implemented. 20 | 21 | 22 | -------------------------------------------------------------------------------- /ga10/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | 9 | 10 | { 11 | "name": "Launch Package", 12 | "type": "go", 13 | "request": "launch", 14 | "mode": "auto", 15 | "program": "${fileDirname}" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /ga10/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.21-bookworm AS build 2 | 3 | 4 | RUN mkdir -p /etc/apt/keyrings && \ 5 | wget -q https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /etc/apt/keyrings/intel-sgx-keyring.asc && \ 6 | echo "deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" > /etc/apt/sources.list.d/intel-sgx.list && \ 7 | apt update && \ 8 | ERT_DEB=edgelessrt_0.4.1_amd64_ubuntu-22.04.deb && \ 9 | wget https://github.com/edgelesssys/edgelessrt/releases/download/v0.4.1/$ERT_DEB && \ 10 | apt-get install -y ./$ERT_DEB build-essential cmake libssl-dev libsgx-dcap-default-qpl libsgx-dcap-ql libsgx-dcap-quote-verify 11 | 12 | # Set destination for COPY 13 | WORKDIR /app 14 | 15 | # Download Go modules 16 | COPY ./go.mod ./go.sum ./ 17 | RUN go mod download 18 | 19 | COPY . ./ 20 | 21 | RUN go get -u 22 | RUN go mod tidy 23 | RUN . /opt/edgelessrt/share/openenclave/openenclaverc && GOOS=linux GOARCH=amd64 go build -o /ga10 ga10.go 24 | 25 | CMD ["/ga10"] -------------------------------------------------------------------------------- /ga10/config.yaml: -------------------------------------------------------------------------------- 1 | #Some general naming 2 | system: 3 | name: ASVR_GO_1 4 | 5 | #MongoDB Configuration 6 | database: 7 | connection: mongodb://127.0.0.1:27017 8 | name: testasvrlocal 9 | 10 | #MQTT Configuration 11 | messaging: 12 | broker: 127.0.0.1 13 | port: 1883 14 | clientid: asvrgo1 15 | 16 | #REST Interface Configuration 17 | rest: 18 | port: 8520 19 | crt: temporary.crt 20 | key: temporary.key 21 | usehttp: false 22 | 23 | #Web Interface Configuration 24 | web: 25 | port: 8540 26 | crt: temporary.crt 27 | key: temporary.key 28 | usehttp: true 29 | 30 | 31 | #Web Interface Configuration 32 | x3270: 33 | port: 3270 34 | 35 | 36 | #Log file 37 | logging: 38 | logfilelocation: /tmp/ga10.log 39 | sessionupdatelogging: false 40 | -------------------------------------------------------------------------------- /ga10/configuration/configuration.go: -------------------------------------------------------------------------------- 1 | package configuration 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "gopkg.in/yaml.v3" 8 | ) 9 | 10 | // The configuration structure also gives the format of the YAML config file 11 | // 12 | // For example 13 | //#Some general naming 14 | //system: 15 | // name: ASVR_GO_1 -- name of the ASVR system. Can be anything sensible 16 | // 17 | //#MongoDB Configuration 18 | //database: 19 | // connection: mongodb://192.168.1.203:27017 -- connection string for the mongodb 20 | // name: test1 -- name of the database to use 21 | // 22 | //#MQTT Configuration 23 | //messaging: 24 | // broker: 192.168.1.203 -- IP address of the MQTT broker 25 | // port: 1883 -- Port to use, typically 1883 26 | // 27 | //#REST Interface Configuration 28 | //rest: 29 | // port: 8520 -- Port to use for the REST API, default is 8520 30 | // crt: temporary.crt -- File containing the certificate to use for the HTTPS server 31 | // key: temporary.key -- File containing the private key for the HTTPS server 32 | // usehttp: true -- Use HTTP (true) instead of HTTPS. Default is false 33 | 34 | type ConfigurationStruct struct { 35 | System struct { 36 | Name string 37 | } 38 | Database struct { 39 | Connection string 40 | Name string 41 | } 42 | Messaging struct { 43 | Broker string 44 | Port uint16 45 | ClientID string 46 | } 47 | Rest struct { 48 | Port string 49 | Crt string 50 | Key string 51 | UseHTTP bool 52 | } 53 | Web struct { 54 | Port string 55 | Crt string 56 | Key string 57 | UseHTTP bool 58 | } 59 | X3270 struct { 60 | Port string 61 | } 62 | Logging struct { 63 | LogFileLocation string 64 | SessionUpdateLogging bool 65 | } 66 | Keylime struct { 67 | ApiUrl string 68 | } 69 | } 70 | 71 | // The exported variable for accessing the configuration structure 72 | var ConfigData *ConfigurationStruct 73 | 74 | // The function that reads the configuraiton file and sets up the configuration structure 75 | // 76 | // If the file is unavailable or in unparsable then this function will panic and exit. 77 | // There is no need to continue if the configuration is borked. 78 | func SetupConfiguration(f string) { 79 | fmt.Println("GA10: Configuration file location: ", f) 80 | 81 | configFile, err := ioutil.ReadFile(f) 82 | if err != nil { 83 | panic(fmt.Sprintf("Configuration file missing. Exiting with error ", err)) 84 | } 85 | 86 | err = yaml.Unmarshal(configFile, &ConfigData) 87 | if err != nil { 88 | panic(fmt.Sprintf("Unable to parse configuration file. Exiting with error ", err)) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ga10/datalayer/count.go: -------------------------------------------------------------------------------- 1 | package datalayer 2 | 3 | import( 4 | "context" 5 | "log" 6 | "reflect" 7 | 8 | // "go.mongodb.org/mongo-driver/mongo/options" 9 | "go.mongodb.org/mongo-driver/bson" 10 | ) 11 | 12 | func Count(coll string) int64 { 13 | //options := options.Count() 14 | count, err := DB.Collection(coll).CountDocuments(context.TODO(), bson.D{}) 15 | 16 | log.Printf("count for %v is %v %v, err is %v",coll,count,reflect.TypeOf(count),err) 17 | 18 | if err != nil { 19 | return -1 20 | } else { 21 | return count 22 | } 23 | } -------------------------------------------------------------------------------- /ga10/datalayer/initialisation.go: -------------------------------------------------------------------------------- 1 | package datalayer 2 | 3 | 4 | func InitialiseDatalayer() { 5 | 6 | initialiseDatabase() 7 | initialiseMessaging() 8 | initialiseInternalDBs() 9 | } -------------------------------------------------------------------------------- /ga10/datalayer/internaldbs.go: -------------------------------------------------------------------------------- 1 | package datalayer 2 | 3 | import( 4 | "a10/structures" 5 | ) 6 | 7 | var RulesDatabase map[string]structures.Rule = make(map[string]structures.Rule) 8 | var ProtocolsDatabase map[string]structures.Protocol = make(map[string]structures.Protocol) 9 | 10 | func initialiseInternalDBs() { 11 | // No initialisation required as the current two internal databases are empty 12 | } -------------------------------------------------------------------------------- /ga10/datalayer/mongo.go: -------------------------------------------------------------------------------- 1 | package datalayer 2 | 3 | import( 4 | "fmt" 5 | "context" 6 | 7 | "a10/configuration" 8 | 9 | "go.mongodb.org/mongo-driver/mongo" 10 | "go.mongodb.org/mongo-driver/mongo/options" 11 | ) 12 | 13 | var DB *mongo.Database 14 | var DBCLIENT *mongo.Client 15 | var ctx = context.TODO() 16 | 17 | 18 | 19 | func initialiseDatabase() { 20 | fmt.Println("GA10: initialising database MONGO connection") 21 | 22 | clientOptions := options.Client().ApplyURI(configuration.ConfigData.Database.Connection) 23 | client, err := mongo.Connect(ctx, clientOptions) 24 | 25 | if err != nil { 26 | panic(err.Error()) 27 | } 28 | 29 | err = client.Ping(ctx,nil) 30 | if err != nil { 31 | panic(err.Error()) 32 | } 33 | 34 | DB = client.Database(configuration.ConfigData.Database.Name) 35 | 36 | fmt.Println("GA10: Database infrastructure MONGO is running") 37 | 38 | DBCLIENT = client 39 | 40 | } -------------------------------------------------------------------------------- /ga10/datalayer/mqtt.go: -------------------------------------------------------------------------------- 1 | package datalayer 2 | 3 | import( 4 | "fmt" 5 | 6 | "a10/configuration" 7 | 8 | mqtt "github.com/eclipse/paho.mqtt.golang" 9 | 10 | ) 11 | 12 | var MESSAGING mqtt.Client 13 | 14 | var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { 15 | fmt.Println("GA10: MQTT connected") 16 | } 17 | 18 | var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { 19 | fmt.Println("GA10: MQTT connection lost. Error %v",err) 20 | } 21 | 22 | func initialiseMessaging() { 23 | fmt.Println("GA10: Initialising message infrastructure MQTT connection") 24 | 25 | var broker = configuration.ConfigData.Messaging.Broker 26 | var port = configuration.ConfigData.Messaging.Port 27 | 28 | opts := mqtt.NewClientOptions() 29 | opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port)) 30 | opts.SetClientID(configuration.ConfigData.Messaging.ClientID) 31 | //opts.SetUsername("me") 32 | //opts.SetPassword("me2") 33 | //opts.SetDefaultPublishHandler(messagePubHandler) 34 | opts.OnConnect = connectHandler 35 | opts.OnConnectionLost = connectLostHandler 36 | 37 | client := mqtt.NewClient(opts) 38 | if token := client.Connect(); token.Wait() && token.Error() != nil { 39 | fmt.Println("GA10: Failed to initialise MQTT connection") 40 | panic(token.Error()) 41 | } 42 | 43 | fmt.Println("GA10: Message infrastructure MQTT is running") 44 | 45 | MESSAGING = client 46 | } -------------------------------------------------------------------------------- /ga10/enclave.json: -------------------------------------------------------------------------------- 1 | { 2 | "exe": "ga10", 3 | "key": "private.pem", 4 | "debug": true, 5 | "heapSize": 512, 6 | "executableHeap": false, 7 | "productID": 1, 8 | "securityVersion": 1, 9 | "mounts": null, 10 | "env": null, 11 | "files": null 12 | } -------------------------------------------------------------------------------- /ga10/go.mod: -------------------------------------------------------------------------------- 1 | module a10 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/eclipse/paho.mqtt.golang v1.4.3 7 | github.com/google/uuid v1.5.0 8 | github.com/labstack/echo/v4 v4.11.4 9 | github.com/racingmars/go3270 v0.0.0-20231111230320-21f273b327b8 10 | go.mongodb.org/mongo-driver v1.13.1 11 | golang.org/x/exp v0.0.0-20240119083558-1b970713d09a 12 | gopkg.in/yaml.v3 v3.0.1 13 | ) 14 | 15 | require github.com/miekg/pkcs11 v1.1.1 16 | 17 | require gopkg.in/square/go-jose.v2 v2.6.0 // indirect 18 | 19 | require ( 20 | github.com/edgelesssys/ego v1.4.1 21 | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect 22 | github.com/golang/snappy v0.0.4 // indirect 23 | github.com/google/go-tpm v0.9.0 24 | github.com/gorilla/websocket v1.5.1 // indirect 25 | github.com/klauspost/compress v1.17.4 // indirect 26 | github.com/labstack/gommon v0.4.2 // indirect 27 | github.com/mattn/go-colorable v0.1.13 // indirect 28 | github.com/mattn/go-isatty v0.0.20 // indirect 29 | github.com/montanaflynn/stats v0.7.1 // indirect 30 | github.com/valyala/bytebufferpool v1.0.0 // indirect 31 | github.com/valyala/fasttemplate v1.2.2 // indirect 32 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 33 | github.com/xdg-go/scram v1.1.2 // indirect 34 | github.com/xdg-go/stringprep v1.0.4 // indirect 35 | github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect 36 | golang.org/x/crypto v0.18.0 // indirect 37 | golang.org/x/net v0.20.0 // indirect 38 | golang.org/x/sync v0.6.0 // indirect 39 | golang.org/x/sys v0.16.0 // indirect 40 | golang.org/x/text v0.14.0 // indirect 41 | golang.org/x/time v0.5.0 // indirect 42 | ) 43 | -------------------------------------------------------------------------------- /ga10/logging/logging.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import( 4 | "log" 5 | "fmt" 6 | "context" 7 | "sync" 8 | "os" 9 | 10 | "a10/utilities" 11 | "a10/datalayer" 12 | "a10/structures" 13 | "a10/configuration" 14 | ) 15 | 16 | 17 | func MakeLogEntry(ch string, op string, itemid string, itemtype string, message string){ 18 | 19 | logentry := structures.LogEntry{ utilities.MakeID(), utilities.MakeTimestamp(), ch, op, itemid, itemtype, message, []byte{} } 20 | 21 | if digest,err := utilities.MakeSHA256(logentry); err != nil { 22 | log.Printf("WARNING: Encoding log entry failed with %w. Entry not made.",err) 23 | } else { 24 | logentry.Hash = digest 25 | 26 | // these can be run in parallel. We don't care about return results 27 | var wg sync.WaitGroup 28 | 29 | wg.Add(3) 30 | 31 | go writeToDB(&wg,logentry) 32 | go writeToMessaging(&wg,logentry) 33 | go writeToLogfile(&wg,logentry) 34 | 35 | wg.Wait() 36 | } 37 | 38 | } 39 | 40 | 41 | func writeToDB(wgrp *sync.WaitGroup, l structures.LogEntry){ 42 | _,_ = datalayer.DB.Collection("log").InsertOne(context.TODO(), l) 43 | 44 | wgrp.Done() 45 | } 46 | 47 | 48 | func writeToMessaging(wgrp *sync.WaitGroup, l structures.LogEntry){ 49 | ch := fmt.Sprintf("AS/%s",l.Channel) 50 | _ = datalayer.MESSAGING.Publish(ch,0,false,makeCSVText(l)) 51 | 52 | wgrp.Done() 53 | } 54 | 55 | 56 | func writeToLogfile(wgrp *sync.WaitGroup, l structures.LogEntry){ 57 | f,err := os.OpenFile(configuration.ConfigData.Logging.LogFileLocation, 58 | os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 59 | if err != nil { 60 | log.Println("Error opening log file ",configuration.ConfigData.Logging.LogFileLocation) 61 | } 62 | defer f.Close() 63 | 64 | if _, err := f.WriteString(makeCSVText(l)); err != nil { 65 | log.Println("Error writring to log file ",configuration.ConfigData.Logging.LogFileLocation) 66 | } 67 | 68 | wgrp.Done() 69 | } 70 | 71 | 72 | func makeCSVText(l structures.LogEntry) string { 73 | return fmt.Sprintf("%s,%v,%s,%s,%s,%s,%q\n",l.ItemID, l.Timestamp, l.Channel, l.Operation, l.RefID, l.RefType, l.Message) 74 | } -------------------------------------------------------------------------------- /ga10/operations/attestation.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import( 4 | "fmt" 5 | 6 | "a10/structures" 7 | "a10/utilities" 8 | ) 9 | 10 | type hashablePartClaim struct { 11 | BodyType string 12 | Header structures.ClaimHeader 13 | Body map[string]interface{} 14 | } 15 | 16 | 17 | 18 | //This function calls the attestation mechanism that eventually calls the TA on some client 19 | // ItemIDs for Element, Policy and String are provided in eid, pid and sid 20 | // A map of additional parameters in aps 21 | func Attest(element structures.Element, policy structures.Policy, session structures.Session, aps map[string]interface{}) (string, error) { 22 | 23 | var body map[string]interface{} = make(map[string]interface{}) 24 | 25 | /* 1. create a protocol object 26 | 2. set the timer start 27 | 3. dispatch control over to the protocol object 28 | 4. stop timer 29 | 5. create claim 30 | 6. store claim 31 | 7. add claim to the session 32 | 8. return 33 | */ 34 | 35 | // Step 1 ****************************************************** 36 | 37 | protocol := element.Protocol 38 | protocolObject,_ := GetProtocol(protocol) 39 | 40 | // TODO: Need to check that the protocol exists here otherwise the acall below fails with a panic 41 | 42 | // Step 2 ****************************************************** 43 | 44 | claimTimerStart := utilities.MakeTimestamp() 45 | 46 | // Step 3 ****************************************************** 47 | 48 | aCALL := protocolObject.CallFunction 49 | returnedBody, ips, bodytype := aCALL( element, policy, session, aps ) 50 | 51 | if bodytype == "*ERROR" { 52 | body["ERROR"] = returnedBody 53 | } else { 54 | body = returnedBody 55 | } 56 | 57 | // Step 4 ****************************************************** 58 | 59 | claimTimerFinish := utilities.MakeTimestamp() 60 | 61 | // Step 5 ****************************************************** 62 | // NB: we have body and bodytype from above 63 | 64 | timing := structures.Timing{ claimTimerStart, claimTimerFinish } 65 | header := structures.ClaimHeader{element, policy, session, timing, aps, ips} 66 | footer,_ := hashAndSignClaim(hashablePartClaim{ bodytype, header, body }) 67 | 68 | c := structures.Claim{ "", bodytype, header, body, footer } 69 | 70 | // Step 6 71 | sid := session.ItemID 72 | 73 | cid,err := AddClaim( c ) // cid a string with the claim ID 74 | if err != nil { 75 | return "",fmt.Errorf("Error adding claim, session %v might still be open: %w",sid,err) 76 | } 77 | 78 | fmt.Printf("Added claim %v\n",cid) 79 | 80 | // if AddClaim fails, we have a bigger problem, see above note 81 | // If there is an error here, then we need a new claim type of "internal error" 82 | // but of course, if we can't add a claim then we can not add an internal error claim ---just dump something on the log! 83 | // plus specific logging to handle this - might denote on seriously fscked TA at the other end? 84 | // This is kind of the same thing that happens if there protocol object ins't found 85 | 86 | // Step 7 87 | 88 | sderr := AddClaimToSession(sid,cid) 89 | if sderr != nil { 90 | return "",fmt.Errorf("Error adding claim %v to session %v. Claim added, session may be still open: %w",cid,sid,err) 91 | } 92 | 93 | // Step 8 94 | 95 | return cid,nil 96 | } 97 | 98 | 99 | -------------------------------------------------------------------------------- /ga10/operations/claims.go: -------------------------------------------------------------------------------- 1 | // This package contains the operations for managing elements in a system 2 | // It provides 3 | package operations 4 | 5 | import( 6 | "fmt" 7 | "context" 8 | 9 | "a10/structures" 10 | "a10/utilities" 11 | "a10/datalayer" 12 | "a10/logging" 13 | 14 | "go.mongodb.org/mongo-driver/mongo/options" 15 | "go.mongodb.org/mongo-driver/bson" 16 | 17 | ) 18 | 19 | func isClaimError(c structures.Claim) bool { 20 | return c.BodyType == structures.CLAIMERROR 21 | } 22 | 23 | func CountClaims() int64 { 24 | return datalayer.Count("claims") 25 | } 26 | 27 | // AddElement is a function that takes and element structure that has a BLANK Itemid field (empty string) and stores that 28 | // element in some database 29 | // Successful storage returns the itemid for that element and a nil error. 30 | // An error is returned if an item id is given as part of the input structure. 31 | func AddClaim(e structures.Claim) (string, error) { 32 | if (e.ItemID != "") { 33 | return "", ErrorItemIDIncluded 34 | } else { 35 | e.ItemID = utilities.MakeID() 36 | _,dberr := datalayer.DB.Collection("claims").InsertOne(context.TODO(), e) 37 | logging.MakeLogEntry("C","add",e.ItemID,"claim","") 38 | return e.ItemID, dberr 39 | } 40 | } 41 | 42 | 43 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database. 44 | func GetClaims() ([]structures.ID, error) { 45 | var claims []structures.ID 46 | 47 | filter := bson.D{ {} } // Get all 48 | options := options.Find().SetProjection(bson.D{{"itemid",1}}) 49 | dbcursor,_ := datalayer.DB.Collection("claims").Find(context.TODO(), filter,options) 50 | dbcursorerror := dbcursor.All(context.TODO(),&claims) 51 | 52 | return claims, dbcursorerror 53 | } 54 | 55 | func GetClaimsAll() ([]structures.Claim, error) { 56 | var claims []structures.Claim 57 | 58 | filter := bson.D{ {} } // Get all 59 | options := options.Find().SetSort(bson.D{{"header.timing.requested",-1}}) 60 | 61 | dbcursor,_ := datalayer.DB.Collection("claims").Find(context.TODO(), filter, options) 62 | dbcursorerror := dbcursor.All(context.TODO(),&claims) 63 | 64 | fmt.Printf("\n********\nClaims\n error %w \n claims %v \n*** \n",claims,dbcursorerror) 65 | 66 | return claims, dbcursorerror 67 | } 68 | 69 | func GetClaimsByElementID(eid string, maximumAmount int64) ([]structures.Claim, error) { 70 | var claims []structures.Claim 71 | 72 | if maximumAmount<1 { 73 | return claims, fmt.Errorf("Maximum amount must be a positive number") 74 | } 75 | 76 | fmt.Println("Getting for claim by element eid = %v\n",eid) 77 | filter := bson.D{ {"header.element.itemid",eid } } // TODO search for itemIDs only 78 | options := options.Find().SetSort(bson.D{{"header.timing.requested",-1}}).SetLimit(maximumAmount) 79 | dbcursor,_ := datalayer.DB.Collection("claims").Find(context.TODO(), filter, options) 80 | dbcursorerror := dbcursor.All(context.TODO(),&claims) 81 | 82 | return claims, dbcursorerror 83 | } 84 | 85 | 86 | // GetElementByItemID returns a single element or error 87 | func GetClaimByItemID(itemid string) (structures.Claim, error) { 88 | var claim structures.Claim 89 | 90 | // discard the cursor, it will be an empty entry if nothing exists 91 | filter := bson.D{ {"itemid", itemid} } 92 | dbcursorerror := datalayer.DB.Collection("claims").FindOne(context.TODO(), filter).Decode(&claim) 93 | 94 | if claim.ItemID == "" { 95 | return structures.Claim{}, ErrorItemNotFound 96 | } else { 97 | return claim, dbcursorerror 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /ga10/operations/log.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import( 4 | "context" 5 | "fmt" 6 | 7 | "a10/structures" 8 | "a10/datalayer" 9 | "a10/utilities" 10 | 11 | "go.mongodb.org/mongo-driver/mongo/options" 12 | "go.mongodb.org/mongo-driver/bson" 13 | 14 | ) 15 | 16 | func CountLogEntries() int64 { 17 | return datalayer.Count("log") 18 | } 19 | 20 | func GetLogEntries(maximumAmount int64) ([]structures.LogEntry,error) { 21 | var logentries []structures.LogEntry 22 | 23 | filter := bson.D{ {} } // Get all 24 | 25 | options := options.Find().SetSort(bson.D{{"timestamp",-1}}).SetLimit(maximumAmount) 26 | dbcursor,_ := datalayer.DB.Collection("log").Find(context.TODO(), filter, options) 27 | dbcursorerror := dbcursor.All(context.TODO(),&logentries) 28 | 29 | return logentries, dbcursorerror 30 | } 31 | 32 | func GetLogEntriesSince(duration string) ([]structures.LogEntry,error) { 33 | var logentries []structures.LogEntry 34 | 35 | ts := utilities.TimeStampHoursAgo(duration) 36 | fmt.Printf("Duration is %v, ts is %v\n",duration,ts) 37 | 38 | filter := bson.D{{"timestamp", bson.D{{"$gt",ts}}}} // Get all since given point in time 39 | 40 | options := options.Find().SetSort(bson.D{{"timestamp",-1}}) 41 | 42 | dbcursor,_ := datalayer.DB.Collection("log").Find(context.TODO(), filter, options) 43 | dbcursorerror := dbcursor.All(context.TODO(),&logentries) 44 | 45 | return logentries, dbcursorerror 46 | } 47 | -------------------------------------------------------------------------------- /ga10/operations/opaqueobjects.go: -------------------------------------------------------------------------------- 1 | // This package contains the operations for managing elements in a system 2 | // It provides 3 | package operations 4 | 5 | import( 6 | "fmt" 7 | "context" 8 | 9 | "a10/structures" 10 | "a10/datalayer" 11 | "a10/logging" 12 | 13 | "go.mongodb.org/mongo-driver/mongo/options" 14 | "go.mongodb.org/mongo-driver/bson" 15 | 16 | ) 17 | 18 | func CountOpaqueOjects() int64 { 19 | return datalayer.Count("hashes") 20 | } 21 | 22 | func AddOpaqueObject(h structures.OpaqueObject) (string, error) { 23 | options := options.Update().SetUpsert(true) 24 | filter := bson.D{{"value",h.Value}} 25 | //update := bson.D{{ "$set", bson.D{{ h }}}} 26 | _,dberr := datalayer.DB.Collection("opaqueobjects").UpdateOne(context.TODO(), filter, h, options) 27 | msg := fmt.Sprintf("%s,%s",h.Type,h.ShortDescription) 28 | logging.MakeLogEntry("IM","add",h.Value,"object",msg) 29 | return h.Value, dberr 30 | 31 | } 32 | 33 | func UpdateOpaqueObject(replacement structures.OpaqueObject) (string, error) { 34 | return AddOpaqueObject(replacement) 35 | } 36 | 37 | func DeleteOpaqueObject(v string) error { 38 | filter := bson.D{{"value",v}} 39 | deleteresult, err := datalayer.DB.Collection("opaqueobjects").DeleteOne(context.TODO(), filter) 40 | 41 | if err != nil { 42 | return err 43 | } else if deleteresult.DeletedCount != 1 { 44 | return ErrorItemNotDeleted 45 | } else { 46 | logging.MakeLogEntry("IM","delete",v,"object","") 47 | return nil 48 | } 49 | } 50 | 51 | 52 | func GetOpaqueObjects() ([]structures.OpaqueObject, error) { 53 | var elems []structures.OpaqueObject 54 | 55 | filter := bson.D{ {} } // Get all 56 | dbcursor,_ := datalayer.DB.Collection("opaqueobjects").Find(context.TODO(), filter) 57 | dbcursorerror := dbcursor.All(context.TODO(),&elems) 58 | 59 | return elems, dbcursorerror 60 | } 61 | 62 | 63 | 64 | // GetElementByItemID returns a single element or error 65 | func GetOpaqueObjectByValue(v string) (structures.OpaqueObject, error) { 66 | var elem structures.OpaqueObject 67 | 68 | // discard the cursor, it will be an empty entry if nothing exists 69 | filter := bson.D{ {"value", v} } 70 | dbcursorerror := datalayer.DB.Collection("opaqueobjects").FindOne(context.TODO(), filter).Decode(&elem) 71 | 72 | if elem.Value == "" { 73 | return structures.OpaqueObject{}, ErrorItemNotFound 74 | } else { 75 | return elem, dbcursorerror 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /ga10/operations/operrors.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import( 4 | "errors" 5 | ) 6 | 7 | var ( 8 | ErrorItemIDIncluded = errors.New("ItemID included") 9 | ErrorDatabaseError = errors.New("Database Error") 10 | 11 | ErrorItemNotUpdated = errors.New("Item not updated") 12 | ErrorItemNotFound = errors.New("Item not found") 13 | ErrorItemNotDeleted = errors.New("Element not deleted") 14 | 15 | 16 | ) -------------------------------------------------------------------------------- /ga10/operations/protocols.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import( 4 | "fmt" 5 | "golang.org/x/exp/maps" 6 | 7 | "a10/structures" 8 | "a10/datalayer" 9 | "a10/logging" 10 | ) 11 | 12 | func CountProtocols() int64 { 13 | return datalayer.Count("protocols") 14 | } 15 | 16 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database. 17 | func GetProtocols() []structures.Protocol { 18 | return maps.Values(datalayer.ProtocolsDatabase) 19 | } 20 | 21 | func GetProtocol(n string) (structures.Protocol, error) { 22 | r,exists := datalayer.ProtocolsDatabase[n] 23 | 24 | if (exists) { 25 | return r,nil 26 | } else { 27 | return r,fmt.Errorf("No such protocol") 28 | } 29 | } 30 | 31 | func AddProtocol(p structures.Protocol) { 32 | k := p.Name 33 | datalayer.ProtocolsDatabase[k] = p 34 | logging.MakeLogEntry("IM","add","","protocol",k) 35 | } -------------------------------------------------------------------------------- /ga10/operations/results.go: -------------------------------------------------------------------------------- 1 | // This package contains the operations for managing elements in a system 2 | // It provides 3 | package operations 4 | 5 | import( 6 | "fmt" 7 | "context" 8 | 9 | "a10/structures" 10 | "a10/utilities" 11 | "a10/datalayer" 12 | "a10/logging" 13 | 14 | "go.mongodb.org/mongo-driver/mongo/options" 15 | "go.mongodb.org/mongo-driver/bson" 16 | 17 | ) 18 | 19 | func CountResults() int64 { 20 | return datalayer.Count("results") 21 | } 22 | 23 | // AddElement is a function that takes and element structure that has a BLANK Itemid field (empty string) and stores that 24 | // element in some database 25 | // Successful storage returns the itemid for that element and a nil error. 26 | // An error is returned if an item id is given as part of the input structure. 27 | func AddResult(e structures.Result) (string, error) { 28 | if (e.ItemID != "") { 29 | return "", ErrorItemIDIncluded 30 | } else { 31 | e.ItemID = utilities.MakeID() 32 | _,dberr := datalayer.DB.Collection("results").InsertOne(context.TODO(), e) 33 | logging.MakeLogEntry("R","add",e.ItemID,"result",fmt.Sprintf("%v",e.Result) ) 34 | return e.ItemID, dberr 35 | } 36 | } 37 | 38 | 39 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database. 40 | func GetResults() ([]structures.ID, error) { 41 | var results []structures.ID 42 | 43 | filter := bson.D{ {} } // Get all 44 | options := options.Find().SetProjection(bson.D{{"itemid",1}}) 45 | dbcursor,_ := datalayer.DB.Collection("results").Find(context.TODO(), filter,options) 46 | dbcursorerror := dbcursor.All(context.TODO(),&results) 47 | 48 | return results, dbcursorerror 49 | } 50 | 51 | 52 | func GetResultsAll() ([]structures.Result, error) { 53 | var results []structures.Result 54 | 55 | filter := bson.D{ {} } // Get all 56 | options := options.Find().SetSort(bson.D{{"verifiedat",-1}}) 57 | dbcursor,_ := datalayer.DB.Collection("results").Find(context.TODO(), filter, options) 58 | dbcursorerror := dbcursor.All(context.TODO(),&results) 59 | 60 | return results, dbcursorerror 61 | } 62 | 63 | 64 | func GetResultsByElementID(eid string, maximumAmount int64) ([]structures.Result, error) { 65 | var Results []structures.Result 66 | 67 | fmt.Printf("getting results for %v\n",eid) 68 | 69 | filter := bson.D{ { "elementid",eid } } // Get all // TODO search for itemIDs only 70 | options := options.Find().SetSort(bson.D{{"verifiedAt",-1}}).SetLimit(maximumAmount) 71 | dbcursor,_ := datalayer.DB.Collection("results").Find(context.TODO(), filter, options) 72 | dbcursorerror := dbcursor.All(context.TODO(),&Results) 73 | 74 | return Results, dbcursorerror 75 | } 76 | 77 | 78 | // GetElementByItemID returns a single element or error 79 | func GetResultByItemID(itemid string) (structures.Result, error) { 80 | var Result structures.Result 81 | 82 | // discard the cursor, it will be an empty entry if nothing exists 83 | filter := bson.D{ {"itemid", itemid} } 84 | dbcursorerror := datalayer.DB.Collection("results").FindOne(context.TODO(), filter).Decode(&Result) 85 | 86 | if Result.ItemID == "" { 87 | return structures.Result{}, ErrorItemNotFound 88 | } else { 89 | return Result, dbcursorerror 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /ga10/operations/rules.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import( 4 | "errors" 5 | "sort" 6 | "golang.org/x/exp/maps" 7 | 8 | "a10/structures" 9 | "a10/datalayer" 10 | "a10/logging" 11 | ) 12 | 13 | func CountRules() int64 { 14 | return datalayer.Count("rules") 15 | } 16 | 17 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database. 18 | func GetRules() []structures.Rule { 19 | keys := maps.Keys(datalayer.RulesDatabase) 20 | sort.Strings(keys) 21 | 22 | vals := make([]structures.Rule, 0) // empty 23 | for _,k := range keys { 24 | vals = append(vals,datalayer.RulesDatabase[k]) 25 | } 26 | return vals 27 | 28 | } 29 | 30 | func GetRule(n string) (structures.Rule, error) { 31 | r,exists := datalayer.RulesDatabase[n] 32 | 33 | if (exists) { 34 | return r,nil 35 | } else { 36 | return r,errors.New("No such rule") 37 | } 38 | } 39 | 40 | func AddRule(r structures.Rule) { 41 | k := r.Name 42 | datalayer.RulesDatabase[k] = r 43 | logging.MakeLogEntry("IM","add","","rule",k) 44 | } -------------------------------------------------------------------------------- /ga10/operations/signingFunctions.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import( 4 | "fmt" 5 | 6 | "crypto" 7 | "crypto/rsa" 8 | "crypto/rand" 9 | 10 | "a10/structures" 11 | "a10/utilities" 12 | ) 13 | 14 | var publickey *rsa.PublicKey 15 | var privatekey *rsa.PrivateKey 16 | 17 | func init() { 18 | fmt.Printf("generating private, public key pair for claim signing - just for this session so no chance to verify later. THese keys MUST be external\n") 19 | 20 | privatekey,_ = rsa.GenerateKey(rand.Reader, 2048) 21 | publickey = &privatekey.PublicKey 22 | } 23 | 24 | 25 | 26 | func hashAndSignClaim(h hashablePartClaim) (structures.ClaimFooter,error) { 27 | digest,err := utilities.MakeSHA256(h) 28 | if err != nil { 29 | return structures.ClaimFooter{ []byte{}, []byte{} }, fmt.Errorf("hashAndSignfailed with %v",err) 30 | } 31 | 32 | signature, _ := rsa.SignPSS(rand.Reader, privatekey, crypto.SHA256, digest, nil) 33 | 34 | err = rsa.VerifyPSS(publickey, crypto.SHA256, digest, signature, nil) 35 | if err!=nil { 36 | return structures.ClaimFooter{ []byte{}, []byte{} }, fmt.Errorf("Verification of hashAndSignfailed with %v",err) 37 | } 38 | 39 | return structures.ClaimFooter{ digest, signature }, nil 40 | } 41 | 42 | 43 | 44 | 45 | 46 | func hashAndSignResult(h hashablePartResult) (structures.ResultFooter,error) { 47 | digest,err := utilities.MakeSHA256(h) 48 | if err != nil { 49 | return structures.ResultFooter{ []byte{}, []byte{} }, fmt.Errorf("hashAndSignfailed with %v",err) 50 | } 51 | 52 | signature, _ := rsa.SignPSS(rand.Reader, privatekey, crypto.SHA256, digest, nil) 53 | 54 | err = rsa.VerifyPSS(publickey, crypto.SHA256, digest, signature, nil) 55 | if err!=nil { 56 | return structures.ResultFooter{ []byte{}, []byte{} }, fmt.Errorf("Verification of hashAndSignfailed with %v",err) 57 | } 58 | 59 | return structures.ResultFooter{ digest, signature }, nil 60 | } 61 | 62 | 63 | 64 | 65 | func hashAndSignSession(h hashablePartSession) (structures.SessionFooter,error) { 66 | digest,err := utilities.MakeSHA256(h) 67 | if err != nil { 68 | return structures.SessionFooter{ []byte{}, []byte{} }, fmt.Errorf("hashAndSignfailed with %v",err) 69 | } 70 | 71 | signature, _ := rsa.SignPSS(rand.Reader, privatekey, crypto.SHA256, digest, nil) 72 | 73 | err = rsa.VerifyPSS(publickey, crypto.SHA256, digest, signature, nil) 74 | if err!=nil { 75 | return structures.SessionFooter{ []byte{}, []byte{} }, fmt.Errorf("Verification of hashAndSignfailed with %v",err) 76 | } 77 | 78 | return structures.SessionFooter{ digest, signature }, nil 79 | } -------------------------------------------------------------------------------- /ga10/otherconfigfiles/local.yaml: -------------------------------------------------------------------------------- 1 | #Some general naming 2 | system: 3 | name: ASVR_GO_1 4 | 5 | #MongoDB Configuration 6 | database: 7 | connection: mongodb://127.0.0.1:27017 8 | name: localasvr 9 | 10 | #MQTT Configuration 11 | messaging: 12 | broker: 127.0.0.1 13 | port: 1883 14 | clientid: ASVR_GO_1_LOCAL 15 | 16 | #REST Interface Configuration 17 | rest: 18 | port: 8520 19 | crt: temporary.crt 20 | key: temporary.key 21 | usehttp: true 22 | 23 | #Web Interface Configuration 24 | web: 25 | port: 8540 26 | crt: temporary.crt 27 | key: temporary.key 28 | usehttp: true 29 | 30 | #Log file 31 | logfile: 32 | location: /tmp/ga10.log 33 | -------------------------------------------------------------------------------- /ga10/otherconfigfiles/nconfig.yaml: -------------------------------------------------------------------------------- 1 | #Some general naming 2 | system: 3 | name: ASVR_GO_1 4 | 5 | #MongoDB Configuration 6 | database: 7 | connection: mongodb://10.144.176.154:27017 8 | name: attestation2 9 | 10 | #MQTT Configuration 11 | messaging: 12 | broker: 10.144.176.154 13 | port: 1883 14 | clientid: ASVR_GO_1 15 | 16 | #REST Interface Configuration 17 | rest: 18 | port: 8520 19 | crt: temporary.crt 20 | key: temporary.key 21 | usehttp: true 22 | 23 | #Web Interface Configuration 24 | web: 25 | port: 8540 26 | crt: temporary.crt 27 | key: temporary.key 28 | usehttp: true 29 | 30 | #Log file 31 | logfile: 32 | location: /tmp/ga10.log 33 | -------------------------------------------------------------------------------- /ga10/protocols/netconfprotocol/public.go: -------------------------------------------------------------------------------- 1 | package netconfprotocol 2 | 3 | import( 4 | "fmt" 5 | "log" 6 | "crypto/rand" 7 | 8 | "a10/structures" 9 | ) 10 | 11 | const nonceSize int = 32 12 | 13 | func Registration() (structures.Protocol) { 14 | intents := []string{"null/good","null/test"} 15 | 16 | return structures.Protocol{"A10NETCONF","POC protocol module for NetConf",Call, intents} 17 | } 18 | 19 | func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{},string) { 20 | 21 | // Create a test body 22 | 23 | rtn := map[string]interface{}{ 24 | "foo":"bar", 25 | "calling": fmt.Sprintf("with protocol %v I would send an intent to %v",e.Protocol,p.Intent), 26 | "aNumber": 42, 27 | } 28 | 29 | nce := make([]byte, nonceSize) 30 | _, _ = rand.Read(nce) 31 | 32 | ips := map[string]interface{}{ 33 | "nonce":nce, 34 | } 35 | 36 | // Check if the policy intent was null/null, if so then return with the bodytype being set to null/test 37 | // or error if the above is false. 38 | // 39 | // Claim bodytype should be set to error and a ClaimError structure returned in an error field 40 | 41 | if p.Intent=="null/null" { 42 | log.Println(" null call worked ") 43 | rtn["worked"] = true 44 | return rtn,ips,"null/test" 45 | } else { 46 | log.Println(" null call bad error ") 47 | rtn["error"] = "Error here" 48 | return rtn,ips,structures.CLAIMERROR 49 | } 50 | } -------------------------------------------------------------------------------- /ga10/protocols/nullprotocol/public.go: -------------------------------------------------------------------------------- 1 | package nullprotocol 2 | 3 | import( 4 | "fmt" 5 | "log" 6 | "crypto/rand" 7 | 8 | "a10/structures" 9 | ) 10 | 11 | const nonceSize int = 32 12 | 13 | func Registration() (structures.Protocol) { 14 | intents := []string{"*/*"} 15 | 16 | return structures.Protocol{"A10NULLPROTOCOL","Testing protocol, always returns a test claim",Call, intents} 17 | } 18 | 19 | func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) { 20 | 21 | // Create a test body 22 | 23 | rtn := map[string]interface{}{ 24 | "foo":"bar", 25 | "calling": fmt.Sprintf("with protocol %v I would send an intent to %v",e.Protocol,p.Intent), 26 | "aNumber": 42, 27 | } 28 | 29 | nce := make([]byte, nonceSize) 30 | _, _ = rand.Read(nce) 31 | 32 | ips := map[string]interface{}{ 33 | "nonce":nce, 34 | } 35 | 36 | // Check if the policy intent was null/null, if so then return with the bodytype being set to null/test 37 | // or error if the above is false. 38 | // 39 | // Claim bodytype should be set to error and a ClaimError structure returned in an error field 40 | 41 | if p.Intent=="null/null" { 42 | log.Println(" null call worked ") 43 | rtn["worked"] = true 44 | return rtn,ips,"null/test" 45 | } else { 46 | log.Println(" null call bad error ") 47 | rtn["error"] = "Error here" 48 | return rtn,ips,structures.CLAIMERROR 49 | } 50 | } -------------------------------------------------------------------------------- /ga10/protocols/registerProtocols.go: -------------------------------------------------------------------------------- 1 | package protocols 2 | 3 | import ( 4 | "a10/operations" 5 | 6 | "a10/protocols/a10httprestv2" 7 | "a10/protocols/marblerun" 8 | "a10/protocols/netconfprotocol" 9 | "a10/protocols/nullprotocol" 10 | "a10/protocols/testcontainerprotocol" 11 | ) 12 | 13 | func RegisterProtocols() { 14 | operations.AddProtocol(a10httprestv2.Registration()) 15 | operations.AddProtocol(nullprotocol.Registration()) 16 | operations.AddProtocol(netconfprotocol.Registration()) 17 | operations.AddProtocol(marblerun.Registration()) 18 | operations.AddProtocol(testcontainerprotocol.Registration()) 19 | } 20 | -------------------------------------------------------------------------------- /ga10/protocols/testcontainerprotocol/public.go: -------------------------------------------------------------------------------- 1 | package testcontainerprotocol 2 | 3 | import( 4 | "fmt" 5 | "crypto/rand" 6 | 7 | "a10/structures" 8 | ) 9 | 10 | const nonceSize int = 32 11 | 12 | func Registration() (structures.Protocol) { 13 | intents := []string{"testcontainers/repoimageintegrity"} 14 | 15 | return structures.Protocol{"TESTCONTAINERPROTOCOL","Test protocol for containers",Call, intents} 16 | } 17 | 18 | func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) { 19 | 20 | // Create a test body 21 | 22 | // create a nonce, because why not? 23 | 24 | nce := make([]byte, nonceSize) 25 | _, _ = rand.Read(nce) 26 | 27 | // add it to the set of parameters supplied to this function 28 | 29 | ips := map[string]interface{}{ 30 | "nonce":nce, 31 | } 32 | 33 | // ************************************** 34 | // When calling the real "trust agent" endpoint, ips would be passed as the parameters to whatever function is called that supports the intent 35 | // This is where the call code goes 36 | // ************************************** 37 | 38 | // return the body - we create a test body here 39 | 40 | rtn := map[string]interface{}{ 41 | "foo":"bar", 42 | "calling": fmt.Sprintf("with protocol %v I would send an intent to %v",e.Protocol,p.Intent), 43 | "aNumber": 42, 44 | } 45 | 46 | // Note, if anything above fails please return an error quote, ie the final string in the return below would be *ERROR 47 | 48 | // rtn is the return body 49 | // ips is the generated parameters, ie: cps + anything else 50 | // stirng contains the type of the result. If this is *ERROR then the claim is an error claim - any later verification over that structure would fail accordingly 51 | 52 | return rtn,ips,"testcontainers/repoimageintegrity" 53 | 54 | } -------------------------------------------------------------------------------- /ga10/rules/nullrule/public.go: -------------------------------------------------------------------------------- 1 | package nullrule 2 | 3 | import( 4 | "a10/structures" 5 | ) 6 | 7 | 8 | func Registration() []structures.Rule { 9 | 10 | ruleS := structures.Rule{ "null_success","A rule that always returns success", CallruleS, false} 11 | ruleF := structures.Rule{ "null_fail","A rule that always returns fail", CallruleF, false} 12 | 13 | ruleV := structures.Rule{ "null_verifycallfail","A rule that always returns verifycallfail error", CallruleV, false} 14 | ruleN := structures.Rule{ "null_noresult","A rule that always returns noresult error", CallruleN, false} 15 | ruleE := structures.Rule{ "null_verifycallerrorattempt","A rule that always returns verifycallerrorattempt error", CallruleE, false} 16 | 17 | ruleMEV := structures.Rule{ "null_missingEV","A rule that always returns missing expected value error", CallruleMEV, false} 18 | ruleRCF := structures.Rule{ "null_rulecallfailure","A rule that always returns rule call failure error", CallruleRCF, false} 19 | ruleU := structures.Rule{ "null_unsetresultvalue","A rule that always returns unste result value error", CallruleU, false} 20 | 21 | 22 | return []structures.Rule{ ruleS, ruleF, ruleV, ruleN, ruleE, ruleMEV, ruleRCF, ruleU } 23 | } 24 | 25 | func CallruleS(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 26 | return structures.Success,"This a demonstration of a success result",nil 27 | } 28 | 29 | func CallruleF(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 30 | return structures.Fail,"This a demonstration of a fail result",nil 31 | } 32 | 33 | func CallruleE(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 34 | return structures.VerifyClaimErrorAttempt,"This a demonstration of verifycallerrorattempt",nil 35 | } 36 | 37 | func CallruleV(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 38 | return structures.VerifyCallFailure,"This a demonstration of a verify call fail result",nil 39 | } 40 | 41 | func CallruleN(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 42 | return structures.NoResult,"This a demonstration of no result",nil 43 | } 44 | 45 | 46 | 47 | func CallruleMEV(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 48 | return structures.MissingExpectedValue,"This a demonstration of missing expected value",nil 49 | } 50 | func CallruleRCF(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 51 | return structures.RuleCallFailure,"This a demonstration of rule call failure",nil 52 | } 53 | func CallruleU(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 54 | return structures.UnsetResultValue,"This a demonstration of unset result value",nil 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /ga10/rules/registerRules.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "a10/operations" 5 | "a10/structures" 6 | 7 | "a10/rules/keylime" 8 | "a10/rules/marblerun" 9 | "a10/rules/nullrule" 10 | "a10/rules/sysrules" 11 | "a10/rules/tpm2rules" 12 | 13 | "a10/rules/testcontainerrules" 14 | ) 15 | 16 | func RegisterRules() { 17 | registerListOfRules(nullrule.Registration()) 18 | registerListOfRules(tpm2rules.Registration()) 19 | registerListOfRules(marblerun.Registration()) 20 | registerListOfRules(testcontainerrules.Registration()) 21 | registerListOfRules(sysrules.Registration()) 22 | registerListOfRules(keylime.Registration()) 23 | } 24 | 25 | func registerListOfRules(rs []structures.Rule) { 26 | for _, r := range rs { 27 | operations.AddRule(r) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ga10/rules/sysrules/public.go: -------------------------------------------------------------------------------- 1 | package sysrules 2 | 3 | import( 4 | "a10/structures" 5 | ) 6 | 7 | 8 | func Registration() []structures.Rule { 9 | 10 | ruleS := structures.Rule{ "sys_taRunningSafely","Checks the the TA is NOT in unsafe mode of operation", Callrulesafe, false} 11 | 12 | 13 | return []structures.Rule{ ruleS } 14 | } 15 | 16 | func Callrulesafe(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 17 | 18 | unsafevalue, ok := claim.Body["unsafe"] 19 | if !ok { 20 | return structures.RuleCallFailure, "TA not of correct type, or not reporting unsafe parameter value", nil 21 | } 22 | 23 | if unsafevalue == true { 24 | return structures.Fail, "TA operating in UNSAFE mode", nil 25 | } else { 26 | return structures.Success, "TA operating in safe mode", nil 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ga10/rules/testcontainerrules/public.go: -------------------------------------------------------------------------------- 1 | package testcontainerrules 2 | 3 | import( 4 | "a10/structures" 5 | "fmt" 6 | "reflect" 7 | ) 8 | 9 | 10 | func Registration() []structures.Rule { 11 | 12 | ruleN := structures.Rule{ "testcontainer_LIFE","The rule returns success if the nunber is 42", CallruleN, false} 13 | ruleX := structures.Rule{ "testcontainer_43","The rule returns success if the nunber is 43 - which will not happen", CallruleX, false} 14 | ruleF := structures.Rule{ "testcontainer_FOOBAR","The rule returns success if the response to foo is bar", CallruleF, false} 15 | 16 | return []structures.Rule{ ruleN, ruleX, ruleF } 17 | } 18 | 19 | func CallruleN(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 20 | 21 | number, ok := (claim.Body)["aNumber"] 22 | if !ok { 23 | return structures.VerifyCallFailure, "Missing body",nil 24 | } 25 | 26 | 27 | 28 | if number==int32(42) { 29 | return structures.Success, "Now what is the question?",nil 30 | } else { 31 | return structures.Fail, "Earth 2 required",nil 32 | } 33 | 34 | } 35 | 36 | 37 | 38 | func CallruleX(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 39 | 40 | number, ok := (claim.Body)["aNumber"] 41 | if !ok { 42 | return structures.VerifyCallFailure, "Missing body",nil 43 | } 44 | 45 | if number==int32(43) { 46 | return structures.Success, "Correctly got the wrong answer",nil 47 | } else { 48 | return structures.Fail, "Earth 2 with more mice required",nil 49 | } 50 | } 51 | 52 | 53 | 54 | func CallruleF(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) { 55 | 56 | foobar, ok := (claim.Body)["foo"] 57 | if !ok { 58 | return structures.VerifyCallFailure, "Missing body",nil 59 | } 60 | 61 | fmt.Printf("\n\nNumber is %v type is %v == %v %v\n\n",foobar,reflect.TypeOf(foobar), foobar=="bar",reflect.TypeOf("bar")) 62 | 63 | 64 | if foobar=="bar" { 65 | return structures.Success, "Correctly got the wrong answer",nil 66 | } else { 67 | return structures.Fail, "Earth 2 with more mice required",nil 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ga10/services/restapi/endpointOpaqueObjects.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "log" 5 | "net/http" 6 | 7 | "a10/operations" 8 | "a10/structures" 9 | 10 | "github.com/labstack/echo/v4" 11 | ) 12 | 13 | type returnOpaqueObjects struct { 14 | Objects []structures.OpaqueObject 15 | Length int 16 | } 17 | 18 | 19 | 20 | func getOpaqueObjects(c echo.Context) error { 21 | elems,err := operations.GetOpaqueObjects() 22 | 23 | if err != nil { 24 | log.Println("err=",err) 25 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 26 | } else { 27 | //Convert elems from []structures.ID into a []string 28 | var elems_str []structures.OpaqueObject 29 | for _,e := range elems { 30 | elems_str = append(elems_str,e) 31 | } 32 | 33 | //Marshall into JSON 34 | elems_struct := returnOpaqueObjects{ elems_str, len(elems_str) } 35 | 36 | return c.JSON(http.StatusOK, elems_struct) 37 | } 38 | } 39 | 40 | func getOpaqueObjectByValue(c echo.Context) error { 41 | value := c.Param("value") 42 | 43 | elem,err := operations.GetOpaqueObjectByValue(value) 44 | 45 | if err != nil { 46 | log.Println("err=",err) 47 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 48 | } else { 49 | return c.JSON(http.StatusOK, elem) 50 | } 51 | } 52 | 53 | 54 | 55 | type postOpaqueObjectReturn struct { 56 | Itemid string `json:"itemid"` 57 | Error string `json:"error"` 58 | } 59 | 60 | 61 | 62 | func postOpaqueObject(c echo.Context) error { 63 | elem := new(structures.OpaqueObject) 64 | 65 | if err := c.Bind(elem); err != nil { 66 | clienterr := postOpaqueObjectReturn{ "",err.Error() } 67 | return c.JSON(http.StatusBadRequest, clienterr) 68 | } 69 | 70 | res,err := operations.AddOpaqueObject(*elem) 71 | 72 | if err!=nil { 73 | response := postOpaqueObjectReturn{ res,err.Error() } 74 | return c.JSON(http.StatusInternalServerError, response) 75 | } else { 76 | response := postOpaqueObjectReturn{ res,"" } 77 | return c.JSON(http.StatusCreated, response) 78 | } 79 | } 80 | 81 | 82 | func putOpaqueObject(c echo.Context) error { 83 | return postOpaqueObject(c) 84 | } 85 | 86 | 87 | 88 | func deleteOpaqueObject(c echo.Context) error { 89 | value := c.Param("value") 90 | 91 | err := operations.DeleteOpaqueObject(value) 92 | 93 | if err != nil { 94 | response := postOpaqueObjectReturn{ value,err.Error() } 95 | return c.JSON(http.StatusInternalServerError, response) 96 | } else { 97 | err = operations.DeleteElement(value) 98 | if err != nil { 99 | response := postOpaqueObjectReturn{ value,err.Error() } 100 | return c.JSON(http.StatusInternalServerError, response) 101 | } else { 102 | response := postOpaqueObjectReturn{ value,"" } 103 | return c.JSON(http.StatusOK, response) 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /ga10/services/restapi/endpointsAttestVerify.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "a10/operations" 8 | "a10/structures" 9 | 10 | "github.com/labstack/echo/v4" 11 | ) 12 | 13 | type postAttestReturn struct { 14 | Itemid string `json:"itemid"` 15 | Error string `json:"error"` 16 | } 17 | 18 | type postVerifyReturn struct { 19 | Itemid string `json:"itemid"` 20 | Result structures.ResultValue `json:"result"` 21 | Error string `json:"error"` 22 | } 23 | 24 | type attestStr struct { 25 | EID string `json:"eid"` 26 | PID string `json:"pid"` 27 | SID string `json:"sid"` 28 | Parameters map[string]interface{} `json:"parameters",bson:"parameters"` 29 | } 30 | 31 | type verifyStr struct { 32 | CID string `json:"cid"` 33 | Rule string `json:"rule"` 34 | SID string `json:"sid"` 35 | Parameters map[string]interface{} `json:"parameters",bson:"parameters"` 36 | } 37 | 38 | func postAttest(c echo.Context) error { 39 | att := new(attestStr) 40 | if err := c.Bind(att); err != nil { 41 | clienterr := postAttestReturn{"", err.Error()} 42 | return c.JSON(http.StatusBadRequest, clienterr) 43 | } 44 | 45 | eid := (*att).EID 46 | pid := (*att).PID 47 | sid := (*att).SID 48 | 49 | element, err := operations.GetElementByItemID(eid) 50 | if err != nil { 51 | fmt.Errorf("Element not found: %v", err) 52 | } 53 | 54 | policy, err := operations.GetPolicyByItemID(pid) 55 | if err != nil { 56 | fmt.Errorf("Policy not found: %v", err) 57 | } 58 | 59 | session, err := operations.GetSessionByItemID(sid) 60 | if err != nil { 61 | fmt.Errorf("Session not found: %v", err) 62 | } 63 | 64 | res, err := operations.Attest(element, policy, session, (*att).Parameters) 65 | 66 | if err != nil { 67 | response := postAttestReturn{res, err.Error()} 68 | return c.JSON(http.StatusInternalServerError, response) 69 | } else { 70 | response := postAttestReturn{res, ""} 71 | return c.JSON(http.StatusAccepted, response) 72 | } 73 | 74 | } 75 | 76 | func postVerify(c echo.Context) error { 77 | att := new(verifyStr) 78 | if err := c.Bind(att); err != nil { 79 | clienterr := postVerifyReturn{"", structures.VerifyCallFailure, err.Error()} 80 | return c.JSON(http.StatusBadRequest, clienterr) 81 | } 82 | 83 | cid := (*att).CID 84 | r := (*att).Rule 85 | sid := (*att).SID 86 | ps := (*att).Parameters 87 | 88 | claim, err := operations.GetClaimByItemID(cid) 89 | if err != nil { 90 | return fmt.Errorf("claim not found: %v", err) 91 | } 92 | 93 | rule, err := operations.GetRule(r) 94 | if err != nil { 95 | return fmt.Errorf("rule not found: %v", rule) 96 | } 97 | 98 | session, err := operations.GetSessionByItemID(sid) 99 | if err != nil { 100 | return fmt.Errorf("session not found: %v", err) 101 | } 102 | 103 | res, rv, err := operations.Verify(claim, rule, session, ps) 104 | 105 | if err != nil { 106 | response := postVerifyReturn{res, rv, err.Error()} 107 | return c.JSON(http.StatusInternalServerError, response) 108 | } else { 109 | response := postVerifyReturn{res, rv, ""} 110 | return c.JSON(http.StatusAccepted, response) 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /ga10/services/restapi/endpointsClaims.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "log" 5 | "net/http" 6 | "strconv" 7 | 8 | "a10/operations" 9 | "a10/structures" 10 | ) 11 | 12 | import( 13 | "github.com/labstack/echo/v4" 14 | ) 15 | 16 | type returnClaims struct { 17 | Claims []string `json:"claims"` 18 | Length int `json:"length"` 19 | } 20 | 21 | func getClaims(c echo.Context) error { 22 | claims,err := operations.GetClaims() 23 | 24 | if err != nil { 25 | log.Println("err=",err) 26 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 27 | } else { 28 | //Convert elems from []structures.ID into a []string 29 | var claims_str []string 30 | for _,e := range claims { 31 | claims_str = append(claims_str,e.ItemID) 32 | } 33 | 34 | //Marshall into JSON 35 | claims_struct := returnClaims{ claims_str, len(claims_str) } 36 | 37 | return c.JSON(http.StatusOK, claims_struct) 38 | } 39 | } 40 | 41 | func getClaim (c echo.Context) error { 42 | itemid := c.Param("itemid") 43 | claim,err := operations.GetClaimByItemID(itemid) 44 | 45 | if err != nil { 46 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 47 | } else { 48 | return c.JSON(http.StatusOK, claim) 49 | } 50 | } 51 | 52 | // GetClaimsByElementID 53 | func getClaimsByElementID (c echo.Context) error { 54 | itemid := c.Param("itemid") 55 | max_query := c.QueryParam("max") 56 | max, err := strconv.ParseInt(max_query, 10, 64) 57 | if err != nil { 58 | max=200 59 | } 60 | 61 | claims,err := operations.GetClaimsByElementID(itemid, max) 62 | 63 | if err != nil { 64 | log.Println("err=",err) 65 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 66 | } else { 67 | //Convert elems from []structures.ID into a []string 68 | var claims_str []string 69 | for _,e := range claims { 70 | claims_str = append(claims_str,e.ItemID) 71 | } 72 | 73 | //Marshall into JSON 74 | claims_struct := returnClaims{ claims_str, len(claims_str) } 75 | 76 | return c.JSON(http.StatusOK, claims_struct) 77 | } 78 | } 79 | 80 | type postClaimReturn struct { 81 | Itemid string `json:"itemid"` 82 | Error string `json:"error"` 83 | } 84 | 85 | func postClaim(c echo.Context) error { 86 | elem := new(structures.Claim) 87 | 88 | if err := c.Bind(elem); err != nil { 89 | clienterr := postClaimReturn{ "",err.Error() } 90 | return c.JSON(http.StatusBadRequest, clienterr) 91 | } 92 | 93 | res,err := operations.AddClaim(*elem) 94 | 95 | if err!=nil { 96 | response := postElementReturn{ res,err.Error() } 97 | return c.JSON(http.StatusInternalServerError, response) 98 | } else { 99 | response := postElementReturn{ res,"" } 100 | return c.JSON(http.StatusCreated, response) 101 | } 102 | } -------------------------------------------------------------------------------- /ga10/services/restapi/endpointsHealth.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "sync" 5 | "net/http" 6 | 7 | "a10/operations" 8 | 9 | "github.com/labstack/echo/v4" 10 | ) 11 | 12 | type healthStructure struct { 13 | Counts counts `json:"counts"` 14 | } 15 | 16 | type counts struct { 17 | Ne int64 `json:"ne"` 18 | Np int64 `json:"Np"` 19 | Nev int64 `json:"Nev"` 20 | Nc int64 `json:"Nc"` 21 | Nr int64 `json:"Nr"` 22 | 23 | Nh int64 `json:"Nh"` 24 | Nrul int64 `json:"Nrul"` 25 | Npol int64 `json:"Npol"` 26 | 27 | Nlog int64 `json:"Nlog"` 28 | } 29 | 30 | // Returns a structure detailing the health of the attestation system 31 | // NB: there was a bit of experimental goroutines here :-) 32 | func objectCount() counts { 33 | 34 | var wg sync.WaitGroup 35 | 36 | wg.Add(9) 37 | 38 | nlog := func() int64 { 39 | defer wg.Done() 40 | return operations.CountLogEntries() 41 | }() 42 | 43 | ne := func() int64 { 44 | defer wg.Done() 45 | return operations.CountElements() 46 | }() 47 | 48 | np := func() int64 { 49 | defer wg.Done() 50 | return operations.CountPolicies() 51 | }() 52 | 53 | nev := func() int64 { 54 | defer wg.Done() 55 | return operations.CountExpectedValues() 56 | }() 57 | 58 | nc := func() int64 { 59 | defer wg.Done() 60 | return operations.CountClaims() 61 | }() 62 | 63 | nr := func() int64 { 64 | defer wg.Done() 65 | return operations.CountResults() 66 | }() 67 | 68 | nh := func() int64 { 69 | defer wg.Done() 70 | return operations.CountOpaqueOjects() 71 | }() 72 | 73 | nrul := func() int64 { 74 | defer wg.Done() 75 | return operations.CountRules() 76 | }() 77 | 78 | npro:= func() int64 { 79 | defer wg.Done() 80 | return operations.CountProtocols() 81 | }() 82 | 83 | wg.Wait() 84 | 85 | return counts{ ne,np,nev,nc,nr,nh,nrul,npro,nlog } 86 | } 87 | 88 | 89 | 90 | 91 | func health(c echo.Context) error { 92 | 93 | hstr := healthStructure{ objectCount() } 94 | 95 | return c.JSON(http.StatusOK, hstr) 96 | } 97 | -------------------------------------------------------------------------------- /ga10/services/restapi/endpointsLog.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "log" 5 | "reflect" 6 | 7 | "net/http" 8 | "strconv" 9 | 10 | "a10/operations" 11 | "a10/structures" 12 | ) 13 | 14 | import( 15 | "github.com/labstack/echo/v4" 16 | ) 17 | 18 | type returnLogEntries struct { 19 | LogEntries []structures.LogEntry `json:"logentries"` 20 | Length int `json:"length"` 21 | Max int64 `json:"max"` 22 | } 23 | 24 | 25 | func getLogEntries(c echo.Context) error { 26 | max_query := c.QueryParam("max") 27 | max, err := strconv.ParseInt(max_query, 10, 64) 28 | if err != nil { 29 | max=200 30 | } 31 | log.Println("maxtype is ",reflect.TypeOf(max)) 32 | 33 | 34 | logentries,err := operations.GetLogEntries(max) 35 | 36 | if err != nil { 37 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 38 | } else { 39 | rtn := returnLogEntries{ logentries, len(logentries), max } 40 | return c.JSON(http.StatusOK, rtn) 41 | } 42 | } 43 | 44 | 45 | type returnLogEntriesSince struct { 46 | LogEntries []structures.LogEntry `json:"logentries"` 47 | Length int `json:"length"` 48 | Duration string `json:"duration"` 49 | } 50 | 51 | 52 | func getLogEntriesSince(c echo.Context) error { 53 | duration_query := c.QueryParam("duration") 54 | 55 | logentries,err := operations.GetLogEntriesSince(duration_query) 56 | 57 | if err != nil { 58 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 59 | } else { 60 | rtn := returnLogEntriesSince{ logentries, len(logentries), duration_query } 61 | return c.JSON(http.StatusOK, rtn) 62 | } 63 | } -------------------------------------------------------------------------------- /ga10/services/restapi/endpointsProtocols.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "fmt" 5 | "net/http" 6 | "a10/operations" 7 | 8 | "github.com/labstack/echo/v4" 9 | ) 10 | 11 | 12 | 13 | 14 | type protocolExternal struct { 15 | Name string `json:"name",bson:"name"` 16 | Description string `json:"description",bson:"description"` 17 | Intents []string `json:"intents",bson:"intents"` 18 | } 19 | 20 | 21 | type returnProtocols struct { 22 | Protocols []protocolExternal `json:"protocols"` 23 | Length int `json:"length"` 24 | } 25 | 26 | 27 | 28 | func getProtocols(c echo.Context) error { 29 | ps := operations.GetProtocols() 30 | 31 | //Convert elems from []structures.Protocol into protocolExternal 32 | var ps_str []protocolExternal 33 | for _,p := range ps { 34 | ps_str = append(ps_str, protocolExternal{ p.Name, p.Description, p.Intents} ) 35 | } 36 | 37 | ps_rtn := returnProtocols{ ps_str, len(ps_str) } 38 | 39 | return c.JSON(http.StatusOK, ps_rtn) 40 | } 41 | 42 | func getProtocol(c echo.Context) error { 43 | p,err := operations.GetProtocol(c.Param("name")) 44 | 45 | if err!=nil { 46 | return c.JSON(http.StatusNotFound,fmt.Errorf("No such protocol, %w",err)) 47 | } else { 48 | extp := protocolExternal{ p.Name, p.Description, p.Intents} 49 | return c.JSON(http.StatusOK,extp) 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /ga10/services/restapi/endpointsResults.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "log" 5 | "net/http" 6 | "strconv" 7 | 8 | "a10/operations" 9 | "a10/structures" 10 | ) 11 | 12 | import( 13 | "github.com/labstack/echo/v4" 14 | ) 15 | 16 | type returnResults struct { 17 | Results []string `json:"results"` 18 | Length int `json:"length"` 19 | } 20 | 21 | func getResults(c echo.Context) error { 22 | Results,err := operations.GetResults() 23 | 24 | if err != nil { 25 | log.Println("err=",err) 26 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 27 | } else { 28 | //Convert elems from []structures.ID into a []string 29 | var Results_str []string 30 | for _,e := range Results { 31 | Results_str = append(Results_str,e.ItemID) 32 | } 33 | 34 | //Marshall into JSON 35 | Results_struct := returnResults{ Results_str, len(Results_str) } 36 | 37 | return c.JSON(http.StatusOK, Results_struct) 38 | } 39 | } 40 | 41 | func getResult (c echo.Context) error { 42 | itemid := c.Param("itemid") 43 | Result,err := operations.GetResultByItemID(itemid) 44 | 45 | if err != nil { 46 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 47 | } else { 48 | return c.JSON(http.StatusOK, Result) 49 | } 50 | } 51 | 52 | // GetResultsByElementID 53 | func getResultsByElementID (c echo.Context) error { 54 | itemid := c.Param("itemid") 55 | max_query := c.QueryParam("max") 56 | max, err := strconv.ParseInt(max_query, 10, 64) 57 | if err != nil { 58 | max=200 59 | } 60 | 61 | Results,err := operations.GetResultsByElementID(itemid, max) 62 | 63 | if err != nil { 64 | log.Println("err=",err) 65 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err)) 66 | } else { 67 | //Convert elems from []structures.ID into a []string 68 | var Results_str []string 69 | for _,e := range Results { 70 | Results_str = append(Results_str,e.ItemID) 71 | } 72 | 73 | //Marshall into JSON 74 | Results_struct := returnResults{ Results_str, len(Results_str) } 75 | 76 | return c.JSON(http.StatusOK, Results_struct) 77 | } 78 | } 79 | 80 | type postResultReturn struct { 81 | Itemid string `json:"itemid"` 82 | Error string `json:"error"` 83 | } 84 | 85 | func postResult(c echo.Context) error { 86 | elem := new(structures.Result) 87 | 88 | if err := c.Bind(elem); err != nil { 89 | clienterr := postResultReturn{ "",err.Error() } 90 | return c.JSON(http.StatusBadRequest, clienterr) 91 | } 92 | 93 | res,err := operations.AddResult(*elem) 94 | 95 | if err!=nil { 96 | response := postElementReturn{ res,err.Error() } 97 | return c.JSON(http.StatusInternalServerError, response) 98 | } else { 99 | response := postElementReturn{ res,"" } 100 | return c.JSON(http.StatusCreated, response) 101 | } 102 | } -------------------------------------------------------------------------------- /ga10/services/restapi/endpointsRules.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "fmt" 5 | 6 | "net/http" 7 | "a10/operations" 8 | 9 | "github.com/labstack/echo/v4" 10 | ) 11 | 12 | type ruleExternal struct { 13 | Name string `json:"name",bson:"name"` 14 | Description string `json:"description",bson:"description"` 15 | NeedsEV bool `json:"needsev",bson:"needsev"` 16 | } 17 | 18 | 19 | type returnRules struct { 20 | Rules []ruleExternal `json:"rules"` 21 | Length int `json:"length"` 22 | } 23 | 24 | func getRules(c echo.Context) error { 25 | rs := operations.GetRules() 26 | 27 | //Convert rs from []structures.Rule into rulesExternal 28 | var rs_str []ruleExternal 29 | for _,r := range rs { 30 | rs_str = append(rs_str, ruleExternal{ r.Name, r.Description, r.NeedsEV} ) 31 | } 32 | 33 | rs_rtn := returnRules{ rs_str, len(rs_str) } 34 | 35 | return c.JSON(http.StatusOK, rs_rtn) 36 | 37 | } 38 | 39 | func getRule(c echo.Context) error { 40 | r,err := operations.GetRule(c.Param("name")) 41 | 42 | if err!=nil { 43 | return c.JSON(http.StatusNotFound,fmt.Errorf("No such rule, %w",err)) 44 | } else { 45 | extr := ruleExternal{ r.Name, r.Description, r.NeedsEV} 46 | return c.JSON(http.StatusOK,extr) 47 | } 48 | } -------------------------------------------------------------------------------- /ga10/services/restapi/resterrors.go: -------------------------------------------------------------------------------- 1 | package restapi 2 | 3 | import( 4 | "fmt" 5 | ) 6 | 7 | type restErrorMessage struct { 8 | ErrorMessage string `json:"error",bson:"error"` 9 | } 10 | 11 | func MakeRESTErrorMessage(e error) restErrorMessage{ 12 | return restErrorMessage{ fmt.Sprintf("%v",e.Error()) } 13 | } -------------------------------------------------------------------------------- /ga10/services/webui/attest.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/labstack/echo/v4" 8 | 9 | "a10/operations" 10 | "a10/structures" 11 | ) 12 | 13 | 14 | type atteststr struct { 15 | ES []structures.Element 16 | PS []structures.Policy 17 | RS []structures.Rule 18 | } 19 | 20 | func showAttest(c echo.Context) error { 21 | es,_ := operations.GetElementsAll() 22 | ps,_ := operations.GetPoliciesAll() 23 | rs:= operations.GetRules() 24 | 25 | as := atteststr{ es,ps,rs } 26 | 27 | return c.Render(http.StatusOK, "attest.html",as) 28 | } 29 | 30 | 31 | type attestrequest struct { 32 | Eid string `form:"eid"` 33 | Pid string `form:"pid"` 34 | Rn []string `form:"rn"` 35 | Av string `form:"av"` 36 | Pps string `form:"pps"` 37 | Rps string `form:"rps"` 38 | Msg string `form:"msg"` 39 | } 40 | 41 | type multipleresultsummary struct { 42 | ItemID string 43 | RuleName string 44 | Message string 45 | Result structures.ResultValue 46 | EVID string 47 | } 48 | 49 | func processAttest(c echo.Context) error { 50 | var attreq attestrequest 51 | 52 | err := c.Bind(&attreq); if err != nil { 53 | fmt.Printf("Error in binding %v",err.Error()) 54 | } 55 | 56 | fmt.Printf("ATTREQ %v\n",attreq) 57 | // Get the objects 58 | e,_ := operations.GetElementByItemID(attreq.Eid) 59 | p,_ := operations.GetPolicyByItemID(attreq.Pid) 60 | 61 | // Open a session 62 | sid,_ := operations.OpenSession(attreq.Msg) 63 | s,_ := operations.GetSessionByItemID(sid) 64 | 65 | // Call attest 66 | // https://stackoverflow.com/questions/47400358/go-converting-json-string-to-mapstringinterface 67 | // should be pps here, but we need to covert the pps from string to map[string]interface{} 68 | empty := make(map[string]interface{}) 69 | 70 | // Call attest 71 | cid,err := operations.Attest(e, p, s, empty) 72 | 73 | fmt.Printf("return after attests %v %v\n",err,cid) 74 | 75 | //Check if we are attesting only 76 | // if so, close the session and redirect to the claim page 77 | if attreq.Av=="AO" { 78 | // Close the session now and return - we are not verifying 79 | _ = operations.CloseSession(sid) 80 | 81 | return c.Redirect(http.StatusSeeOther, "/claim/"+cid) 82 | } 83 | 84 | // And now we continue with the verification 85 | // first we need the claim just generated 86 | 87 | cl,_ := operations.GetClaimByItemID(cid) 88 | 89 | // And perform the verifications <--- note the plural 90 | // This bit needs to be parallelised 91 | 92 | for _,rn := range attreq.Rn { 93 | r,_ := operations.GetRule(rn) 94 | fmt.Printf("** verify %v\n",r) 95 | 96 | rid,rv,err := operations.Verify(cl,r,s,empty) // rps conversion goes here 97 | fmt.Printf("results of verify %v - %v - %v\n",err,rv,rid) 98 | 99 | } 100 | // end of parallelism 101 | 102 | 103 | // Close the session 104 | _ = operations.CloseSession(sid) 105 | 106 | // Now we render the multiple (or even just one!) results 107 | 108 | return c.Redirect(http.StatusSeeOther, "/session/"+sid) 109 | } -------------------------------------------------------------------------------- /ga10/services/webui/claims.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/labstack/echo/v4" 8 | 9 | "a10/operations" 10 | ) 11 | 12 | 13 | func showClaims(c echo.Context) error { 14 | es,_ := operations.GetClaimsAll() 15 | fmt.Printf("remdering element %v\n",len(es)) 16 | 17 | return c.Render(http.StatusOK, "claims.html",es) 18 | } 19 | 20 | func showClaim(c echo.Context) error { 21 | x,_ := operations.GetClaimByItemID(c.Param("itemid")) 22 | 23 | return c.Render(http.StatusOK, "claim.html",x) 24 | } -------------------------------------------------------------------------------- /ga10/services/webui/elements.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "fmt" 5 | "net/http" 6 | "encoding/json" 7 | 8 | "github.com/labstack/echo/v4" 9 | 10 | "a10/operations" 11 | "a10/structures" 12 | ) 13 | 14 | type elementsStructure struct { 15 | E structures.Element 16 | CS []structures.Claim 17 | RS []structures.Result 18 | } 19 | 20 | func showElements(c echo.Context) error { 21 | es,_ := operations.GetElementsAll() 22 | fmt.Printf("remdering element %v\n",len(es)) 23 | 24 | return c.Render(http.StatusOK, "elements.html",es) 25 | } 26 | 27 | func showElement(c echo.Context) error { 28 | e,_ := operations.GetElementByItemID(c.Param("itemid")) 29 | 30 | fmt.Printf(" cparam is %v and e.ItemId is %v\n",c.Param("itemid"),e.ItemID) 31 | 32 | cs,_ := operations.GetClaimsByElementID(e.ItemID,10) 33 | rs,_ := operations.GetResultsByElementID(e.ItemID,10) 34 | 35 | fmt.Printf("showElement %v\n",c.Param("itemid")) 36 | 37 | es := elementsStructure{ e,cs,rs } 38 | 39 | return c.Render(http.StatusOK, "element.html",es) 40 | } 41 | 42 | func newElement(c echo.Context) error { 43 | return c.Render(http.StatusOK, "editelement.html",nil) 44 | } 45 | 46 | 47 | func processNewElement(c echo.Context) error { 48 | elemdata := c.FormValue("elementdata") 49 | 50 | var newelem structures.Element 51 | 52 | err := json.Unmarshal([]byte(elemdata), &newelem) 53 | 54 | if err != nil { 55 | fmt.Printf("error is %v\n",err.Error()) 56 | return c.Redirect(http.StatusSeeOther, "/new/element") 57 | } 58 | 59 | fmt.Printf(" fv%v\n",newelem) 60 | eid,err := operations.AddElement(newelem) 61 | fmt.Printf(" eid=%v,err=%v\n",eid,err) 62 | 63 | return c.Redirect(http.StatusSeeOther, "/elements") 64 | } -------------------------------------------------------------------------------- /ga10/services/webui/expectedvalues.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/labstack/echo/v4" 8 | 9 | "a10/operations" 10 | "a10/structures" 11 | 12 | ) 13 | 14 | 15 | type evstruct struct { 16 | EV structures.ExpectedValue 17 | E structures.Element 18 | P structures.Policy 19 | } 20 | 21 | func showExpectedValues(c echo.Context) error { 22 | fmt.Println("here") 23 | es,_ := operations.GetExpectedValuesAll() 24 | 25 | evs := []evstruct{} 26 | 27 | for _,j := range es { 28 | e,_ := operations.GetElementByItemID(j.ElementID) 29 | p,_ := operations.GetPolicyByItemID(j.PolicyID) 30 | evs = append( evs, evstruct{j,e,p} ) 31 | } 32 | 33 | 34 | 35 | 36 | return c.Render(http.StatusOK, "evs.html", evs) 37 | } 38 | 39 | func showExpectedValue(c echo.Context) error { 40 | ev,_ := operations.GetExpectedValueByItemID(c.Param("itemid")) 41 | 42 | e,_ := operations.GetElementByItemID(ev.ElementID) 43 | p,_ := operations.GetPolicyByItemID(ev.PolicyID) 44 | 45 | evstr := evstruct{ ev,e,p} 46 | return c.Render(http.StatusOK, "ev.html",evstr) 47 | } 48 | 49 | 50 | func newExpectedValue(c echo.Context) error { 51 | return c.Render(http.StatusOK, "editexpectedvalue.html",nil) 52 | } 53 | -------------------------------------------------------------------------------- /ga10/services/webui/homepages.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "fmt" 5 | "os" 6 | "net/http" 7 | 8 | "github.com/labstack/echo/v4" 9 | 10 | "a10/configuration" 11 | "a10/operations" 12 | ) 13 | 14 | type homepagestructure struct { 15 | Nes int 16 | Nps int 17 | Nevs int 18 | Ncs int 19 | Nrs int 20 | Nprs int 21 | Nhs int 22 | Nses int64 23 | Nrus int 24 | Nlog int64 25 | Szlog int64 26 | Cfg *configuration.ConfigurationStruct 27 | } 28 | 29 | func homepage(c echo.Context) error { 30 | var hps homepagestructure 31 | 32 | es,_ := operations.GetElements() 33 | ps,_ := operations.GetPolicies() 34 | evs,_ := operations.GetExpectedValues() 35 | cs,_ := operations.GetClaims() 36 | rs,_ := operations.GetResults() 37 | nprs := operations.GetProtocols() 38 | nhs,_ := operations.GetOpaqueObjects() 39 | nrus := operations.GetRules() 40 | 41 | hps.Nes = len(es) 42 | hps.Nps = len(ps) 43 | hps.Nevs = len(evs) 44 | hps.Ncs = len(cs) 45 | hps.Nrs = len(rs) 46 | 47 | hps.Nprs = len(nprs) 48 | hps.Nhs = len(nhs) 49 | hps.Nrus = len(nrus) 50 | 51 | hps.Nlog = operations.CountLogEntries() 52 | hps.Nses = operations.CountSessions() 53 | 54 | lsz,lerr := os.Stat(configuration.ConfigData.Logging.LogFileLocation) 55 | if lerr != nil { 56 | hps.Szlog = -1 57 | } else { 58 | hps.Szlog = lsz.Size() 59 | } 60 | 61 | hps.Cfg = configuration.ConfigData 62 | 63 | fmt.Printf("hps is %v\n",hps) 64 | 65 | return c.Render(http.StatusOK, "home.html",hps) 66 | } 67 | 68 | 69 | 70 | func helppage(c echo.Context) error { 71 | return c.Render(http.StatusOK, "help.html", nil) 72 | } 73 | 74 | func aboutpage(c echo.Context) error { 75 | return c.Render(http.StatusOK, "about.html", nil) 76 | } -------------------------------------------------------------------------------- /ga10/services/webui/log.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "net/http" 5 | "strconv" 6 | 7 | "github.com/labstack/echo/v4" 8 | 9 | "a10/operations" 10 | "a10/structures" 11 | ) 12 | 13 | type logstr struct { 14 | LogEntries []structures.LogEntry 15 | Count int64 16 | Amount int64 17 | Duration string 18 | } 19 | 20 | func showLog(c echo.Context) error { 21 | max_query := c.QueryParam("max") 22 | max, err := strconv.ParseInt(max_query, 10, 64) 23 | if err != nil { 24 | max=200 25 | } 26 | 27 | es,_ := operations.GetLogEntries(max) 28 | nl := operations.CountLogEntries() 29 | 30 | ls := logstr{ es, nl, max, "always"} 31 | 32 | return c.Render(http.StatusOK, "log.html",ls) 33 | } 34 | 35 | 36 | 37 | func showLogSince(c echo.Context) error { 38 | duration := c.QueryParam("duration") 39 | 40 | es,_ := operations.GetLogEntriesSince(duration) 41 | nl := int64(len(es)) 42 | 43 | ls := logstr{ es, nl, nl, duration } 44 | 45 | return c.Render(http.StatusOK, "log.html",ls) 46 | } -------------------------------------------------------------------------------- /ga10/services/webui/opaqueobjects.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "net/http" 5 | 6 | "github.com/labstack/echo/v4" 7 | 8 | "a10/operations" 9 | ) 10 | 11 | 12 | func showOpaqueObjects(c echo.Context) error { 13 | os,_ := operations.GetOpaqueObjects() 14 | 15 | return c.Render(http.StatusOK, "opaqueobjects.html",os) 16 | } 17 | 18 | func showOpaqueObject(c echo.Context) error { 19 | o,_ := operations.GetOpaqueObjectByValue(c.Param("name")) 20 | 21 | return c.Render(http.StatusOK, "opaqueobject.html", o) 22 | } -------------------------------------------------------------------------------- /ga10/services/webui/policies.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | 8 | "github.com/labstack/echo/v4" 9 | 10 | "a10/operations" 11 | "a10/structures" 12 | ) 13 | 14 | func showPolicies(c echo.Context) error { 15 | es, _ := operations.GetPoliciesAll() 16 | return c.Render(http.StatusOK, "policies.html", es) 17 | } 18 | 19 | func showPolicy(c echo.Context) error { 20 | e, _ := operations.GetPolicyByItemID(c.Param("itemid")) 21 | return c.Render(http.StatusOK, "policy.html", e) 22 | } 23 | 24 | func newPolicy(c echo.Context) error { 25 | return c.Render(http.StatusOK, "editpolicy.html", nil) 26 | } 27 | 28 | func processNewPolicy(c echo.Context) error { 29 | elemdata := c.FormValue("policydata") 30 | 31 | var newPolicy structures.Policy 32 | 33 | err := json.Unmarshal([]byte(elemdata), &newPolicy) 34 | 35 | if err != nil { 36 | fmt.Printf("error is %v\n", err.Error()) 37 | return c.Redirect(http.StatusSeeOther, "/new/policy") 38 | } 39 | 40 | fmt.Printf(" fv%v\n", newPolicy) 41 | eid, err := operations.AddPolicy(newPolicy) 42 | fmt.Printf(" eid=%v,err=%v\n", eid, err) 43 | 44 | return c.Redirect(http.StatusSeeOther, "/policies") 45 | } 46 | -------------------------------------------------------------------------------- /ga10/services/webui/protocols.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "net/http" 5 | 6 | "github.com/labstack/echo/v4" 7 | 8 | "a10/operations" 9 | ) 10 | 11 | 12 | func showProtocols(c echo.Context) error { 13 | ps := operations.GetProtocols() 14 | 15 | return c.Render(http.StatusOK, "protocols.html",ps) 16 | } 17 | 18 | -------------------------------------------------------------------------------- /ga10/services/webui/results.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "net/http" 5 | 6 | "github.com/labstack/echo/v4" 7 | 8 | "a10/operations" 9 | "a10/structures" 10 | ) 11 | 12 | 13 | type resultsstr struct { 14 | ItemID string 15 | RuleName string 16 | VerifiedAt structures.Timestamp 17 | Result structures.ResultValue 18 | EVEName string 19 | EVEID string 20 | EVPName string 21 | EVPID string 22 | EV_Name string 23 | EV_ItemID string 24 | ClaimID string 25 | SessionID string 26 | Message string 27 | Footer structures.ResultFooter 28 | } 29 | 30 | func showResults(c echo.Context) error { 31 | 32 | rsstr := []resultsstr{} 33 | 34 | 35 | rs,_ := operations.GetResultsAll() 36 | for _,j := range rs { 37 | ev,_ := operations.GetExpectedValueByItemID(j.ExpectedValue.ItemID) 38 | e,_ := operations.GetElementByItemID(ev.ElementID) 39 | p,_ := operations.GetPolicyByItemID(ev.PolicyID) 40 | 41 | rsstr = append( rsstr, resultsstr{ j.ItemID, j.RuleName,j.VerifiedAt,j.Result,e.Name,e.ItemID,p.Name,p.ItemID,ev.Name,ev.ItemID,j.ClaimID,j.Session.ItemID,j.Message,j.Footer } ) 42 | } 43 | 44 | 45 | return c.Render(http.StatusOK, "results.html", rsstr) 46 | } 47 | 48 | 49 | 50 | type resultsstrext struct { 51 | R resultsstr 52 | } 53 | 54 | func showResult(c echo.Context) error { 55 | r,_ := operations.GetResultByItemID(c.Param("itemid")) 56 | 57 | ev,_ := operations.GetExpectedValueByItemID(r.ExpectedValue.ItemID) 58 | e,_ := operations.GetElementByItemID(ev.ElementID) 59 | p,_ := operations.GetPolicyByItemID(ev.PolicyID) 60 | 61 | rsstr := resultsstr{ r.ItemID, r.RuleName, r.VerifiedAt, r.Result,e.Name,e.ItemID,p.Name,p.ItemID,ev.Name,ev.ItemID,r.ClaimID,r.Session.ItemID,r.Message,r.Footer } 62 | rsstrext := resultsstrext{ rsstr } 63 | 64 | return c.Render(http.StatusOK, "result.html", rsstrext) 65 | } 66 | -------------------------------------------------------------------------------- /ga10/services/webui/rules.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "net/http" 5 | 6 | "github.com/labstack/echo/v4" 7 | 8 | "a10/operations" 9 | ) 10 | 11 | 12 | func showRules(c echo.Context) error { 13 | rs := operations.GetRules() 14 | 15 | return c.Render(http.StatusOK, "rules.html",rs) 16 | } 17 | 18 | -------------------------------------------------------------------------------- /ga10/services/webui/sessions.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import( 4 | "net/http" 5 | "github.com/labstack/echo/v4" 6 | 7 | "a10/operations" 8 | "a10/structures" 9 | ) 10 | 11 | type claimsummary struct { 12 | ItemID string 13 | BodyType string 14 | } 15 | 16 | type resultsummary struct{ 17 | ItemID string 18 | Result structures.ResultValue 19 | RuleName string 20 | VerifiedAt structures.Timestamp 21 | } 22 | 23 | 24 | func showSessions(c echo.Context) error { 25 | s,_ := operations.GetSessionsAll() 26 | 27 | return c.Render(http.StatusOK, "sessions.html",s) 28 | } 29 | 30 | 31 | 32 | 33 | type claimanalytics struct { 34 | Valid int 35 | Errs int 36 | } 37 | 38 | type resultanalytics struct { 39 | Pass int 40 | Fail int 41 | Verifyfail int 42 | Verifycallattempt int 43 | Noresult int 44 | Missineexpectedvalue int 45 | Rulecallfailure int 46 | Unsetresultvalue int 47 | } 48 | 49 | type sessionsummary struct { 50 | S structures.Session 51 | CS []claimsummary 52 | RS []resultsummary 53 | CA claimanalytics 54 | RA resultanalytics 55 | } 56 | 57 | 58 | func showSession(c echo.Context) error { 59 | s,_ := operations.GetSessionByItemID(c.Param("itemid")) 60 | 61 | cs := make([]claimsummary,0) 62 | for _,i := range s.ClaimList { 63 | cl,_ := operations.GetClaimByItemID(i) 64 | cs = append(cs, claimsummary{ cl.ItemID, cl.BodyType }) 65 | } 66 | 67 | rs := make([]resultsummary,0) 68 | for _,i := range s.ResultList { 69 | rl,_ := operations.GetResultByItemID(i) 70 | rs = append(rs, resultsummary{ rl.ItemID, rl.Result, rl.RuleName, rl.VerifiedAt }) 71 | } 72 | 73 | sstr := sessionsummary{ s, cs, rs, genclaimanalytics(cs), genresultanalytics(rs) } 74 | return c.Render(http.StatusOK, "session.html", sstr) 75 | } 76 | 77 | 78 | func genclaimanalytics( cs []claimsummary ) claimanalytics{ 79 | var valid int = 0 80 | var errs int = 0 81 | 82 | for _,c := range cs { 83 | if c.BodyType == "*ERROR" { 84 | errs ++ 85 | } else { 86 | valid ++ 87 | } 88 | } 89 | 90 | return claimanalytics{ valid, errs } 91 | } 92 | 93 | func genresultanalytics( rs []resultsummary ) resultanalytics{ 94 | var pass int = 0 95 | var fail int = 0 96 | var verifyfail int = 0 97 | var verifycallattempt int = 0 98 | var noresult int = 0 99 | var missineexpectedvalue int = 0 100 | var rulecallfailure int = 0 101 | var unsetresultvalue int = 0 102 | 103 | for _,r := range rs { 104 | switch r.Result { 105 | case structures.Success : 106 | pass ++ 107 | case structures.Fail : 108 | fail ++ 109 | case structures.VerifyCallFailure : 110 | verifyfail ++ 111 | case structures.VerifyClaimErrorAttempt: 112 | verifycallattempt ++ 113 | case structures.NoResult : 114 | noresult ++ 115 | case structures.MissingExpectedValue : 116 | missineexpectedvalue ++ 117 | case structures.RuleCallFailure : 118 | rulecallfailure ++ 119 | case structures.UnsetResultValue : 120 | unsetresultvalue ++ 121 | } 122 | 123 | } 124 | 125 | return resultanalytics{ pass,fail,verifyfail,verifycallattempt,noresult,missineexpectedvalue,rulecallfailure,unsetresultvalue } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /ga10/services/webui/templatefunctions.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "time" 7 | 8 | "encoding/base64" 9 | "encoding/hex" 10 | 11 | "a10/structures" 12 | "a10/utilities" 13 | 14 | "github.com/google/go-tpm/legacy/tpm2" 15 | ) 16 | 17 | // No idea if this works but it is supposed to be in the html files 18 | func EpochToUTC(epoch structures.Timestamp) string { 19 | sec, err := strconv.ParseInt(fmt.Sprintf("%v", epoch), 10, 64) 20 | if err != nil { 21 | t := time.Unix(0, 0) 22 | return fmt.Sprintf("%v", t.UTC()) 23 | } 24 | t := time.Unix(0, sec) 25 | return fmt.Sprintf("%v", t.UTC()) 26 | } 27 | 28 | func DefaultMessage() string { 29 | return "Single invocation from WebUI at " + EpochToUTC(utilities.MakeTimestamp()) 30 | } 31 | 32 | func Base64decode(u string) string { 33 | d, _ := base64.StdEncoding.DecodeString(u) 34 | return string(d) 35 | } 36 | 37 | func EncodeAsHexString(b []byte) string { 38 | return hex.EncodeToString(b) 39 | } 40 | 41 | func TCGAlg(h int32) string { 42 | return tpm2.Algorithm(h).String() 43 | } 44 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/attest.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Attest

3 | 4 |
5 | 6 |
7 |
8 | 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 |
17 | 18 |
19 |
20 | 21 | 26 |
27 | 28 |
29 | 30 | 31 | 36 |
37 | 38 |
39 | 40 | 41 | 46 |
47 |
48 | 49 |
50 | 51 | 52 |
53 |
54 | 55 | Operation: 56 | 57 |
    58 |
  • 62 |
  • 66 |
67 | 68 | If "attest only" is selected, then the rule selection and rule parameters are ignored 69 |
70 | 71 |
72 | 73 | 74 |
75 | 76 |
77 | 78 | 79 |
80 |
81 |
82 | 83 |
84 | 85 |
86 | 87 | 88 | {{end}} -------------------------------------------------------------------------------- /ga10/services/webui/templates/attestsummary.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Session

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | {{ else }} 18 | 19 | {{ end }} 20 | 21 | 22 | 23 | 24 | 25 | 26 |
FieldValue
ItemID {{ .ItemID }}
Opened {{ epochToUTC .Timing.Opened }}
Closed 15 | {{ if eq .Timing.Closed "0" }} 16 | Session still open {{ epochToUTC .Timing.Closed }}
#Claims {{ len .ClaimList }}
#Results {{ len .ResultList }}
Message {{ .Message }}
27 | 28 | 29 |

Claims

30 | 31 | 36 | 37 | 38 |

Results

39 | 40 | 45 | 46 | 47 | {{end}} 48 | 49 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GA10 Web User Interface 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 80 | 81 |
82 | 83 |
84 | {{block "content" .}}{{end}} 85 |
86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/claim.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 | 3 |

Claim

4 | 5 |
6 |
7 |
8 | 9 |
Header
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
FieldValue
ItemID {{ .ItemID }}
BodyType {{ .BodyType }}
Element {{ .Header.Element.Name }}
-- Protocol {{ .Header.Element.Protocol }}
-- Endpoint {{ .Header.Element.Endpoint }}
Policy {{ .Header.Policy.Name }}
-- Intent {{ .Header.Policy.Intent }}
Session {{ .Header.Session.ItemID }}
Additional Parameters {{ .Header.AdditionalParameters }}
Call Parameters {{ .Header.CallParameters }}
Requested {{ epochToUTC .Header.Timing.Requested }}
Received {{ epochToUTC .Header.Timing.Received }}
32 | 33 |
34 |
35 | 36 |
Footer
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
FieldValue
Hash {{ encodeAsHexString .Footer.Hash }}
Signature {{ encodeAsHexString .Footer.Signature }}
49 | 50 |
51 |
52 |
53 | 54 |
Body:
55 | 56 | {{ if eq .BodyType "*ERROR" }} 57 |

{{ .BodyType }}

58 | {{ template "claim_ERROR.html" .Body }} 59 | {{ end }} 60 | 61 | {{ if eq .BodyType "sys/info" }} 62 |

{{ .BodyType }}

63 | {{ template "genericList.html" .Body }} 64 | {{ end }} 65 | 66 | {{ if eq .BodyType "ima/asciilog" }} 67 |

{{ .BodyType }}

68 | {{ template "claim_ima.html" .Body }} 69 | {{ end }} 70 | 71 | {{ if eq .BodyType "tpm2/pcrs" }} 72 |

{{ .BodyType }}

73 | {{ template "claim_tpm2pcrs.html" .Body }} 74 | {{ end }} 75 | 76 | {{ if eq .BodyType "tpm2/quote" }} 77 |

{{ .BodyType }}

78 | {{ template "claim_quote.html" .Body.parsed }} 79 | {{ end }} 80 | 81 |
82 |
Raw
83 | {{ .Body }} 84 | 85 | {{end}} 86 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/claim_ERROR.html: -------------------------------------------------------------------------------- 1 | {{define "claim_ERROR.html"}} 2 | 3 | 4 | {{ range $key, $value := .ERROR }} 5 | 6 | {{ end }} 7 | 8 |
{{ $key }} {{ $value }}
9 | {{end}} 10 | 11 | 12 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/claim_ima.html: -------------------------------------------------------------------------------- 1 | {{define "claim_ima.html"}} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
FieldValue
Encoding details {{ .encoded }} {{ .encodedlength }} bytes encoded, {{ .unencodedlength }} bytes original
IMA ASCII Log {{ base64decode .asciilog }}
16 | 17 | {{end}} 18 | 19 | 20 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/claim_quote.html: -------------------------------------------------------------------------------- 1 | {{define "claim_quote.html"}} 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 31 | {{ if eq .signature.Alg 20 }} 32 | 33 | {{ else }} 34 | 35 | {{ end }} 36 | 37 | 38 | 39 | 40 |
PCR Digest{{ .quote.AttestedQuoteInfo.PCRDigest }}
PCR Selection{{ tcgAlg .quote.AttestedQuoteInfo.PCRSelection.Hash }} : 7 | {{ range .quote.AttestedQuoteInfo.PCRSelection.PCRs }} 8 | {{ . }} 9 | {{ end }} 10 |
Firmware{{ .quote.FirmwareVersion }}
Magic & Type{{ .quote.Magic }}, {{ .quote.Type }}
Extra Data{{ .quote.ExtraData }}
Clock{{ .quote.ClockInfo.Clock }}
Reset Count{{ .quote.ClockInfo.ResetCount }}
Restart Count{{ .quote.ClockInfo.RestartCount }}
Safe 20 | {{ if .quote.ClockInfo.Safe}} 21 | Safe ({{ .quote.ClockInfo.Safe }}) 22 | {{ else }} 23 | Unsafe ({{ .quote.ClockInfo.Safe }}) 24 | {{ end }} 25 |
Qualified Signer{{ .quote.QualifiedSigner.Digest.Alg }} {{ .quote.QualifiedSigner.Digest.Value }}
Signing Algorithm{{ tcgAlg .signature.Alg }}
RSA{{ tcgAlg .signature.RSA.HashAlg }} {{ .signature.RSA.Signature }}
ECC{{ tcgAlg .signature.ECC.HashAlg }} {{ .signature.ECC.Signature }}
41 | 42 | {{end}} 43 | 44 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/claim_tpm2pcrs.html: -------------------------------------------------------------------------------- 1 | {{define "claim_tpm2pcrs.html"}} 2 | 3 | 4 | {{ range $key, $value := . }} 5 | 6 | 19 | {{ end }} 20 | 21 |
{{ $key }} 7 | 8 | 9 | 10 | {{ range $pkey, $pvalue := $value }} 11 | 12 | 13 | 14 | {{ end }} 15 | 16 |
{{ $pkey }}{{ $pvalue }}
17 | 18 |
22 | {{end}} 23 | 24 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/claims.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Claims

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {{ range . }} 16 | {{ if eq .BodyType "*ERROR"}} 17 | 18 | {{else}} 19 | 20 | {{end}} 21 | 22 | 23 | 24 | 25 | 26 | 27 | {{end}} 28 | 29 |
BodyTypeRequestedReceivedElementPolicySession
{{ .BodyType }}{{ epochToUTC .Header.Timing.Requested }}{{ epochToUTC .Header.Timing.Received }}{{ .Header.Element.Name }}{{ .Header.Policy.Name }}{{ .Header.Session.ItemID }}
30 | {{end}} 31 | 32 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/editelement.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Element

3 | 4 |
5 |
6 |
7 |
8 | 9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 |
17 |

Instructions

18 |

The above must be valid JSON

19 |

The protocol must be of a valid type

20 |

The UEFI, TPM2, IMA and TXT sections can be removed if these do not apply

21 |

If a new element is being created, then the itemid field will be overwritten and an identifier automatically generated

22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | {{end}} 30 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/editexpectedvalue.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Expected Value

3 |
4 |
5 |
6 | 7 | 13 |
14 |
15 | 16 | 22 |
23 |
24 |
25 |
26 |
27 |
28 | 29 | 30 |
31 | 32 |
33 | 34 |
35 | 36 |
37 |
38 |
39 |

Instructions

40 |

The above expected value parameters (evs field) must be valid JSON

41 |

The expected value for the given element and policy must be unique

42 |

If a new expected value is being created, then the itemid field will be overwritten and an identifier automatically generated

43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | {{end}} 51 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/editpolicy.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Policy

3 |
4 |
5 |
6 |
7 | 8 |
9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 |

Instructions

17 |

The above must be valid JSON

18 |

If a new policy is being created, then the itemid field will be overwritten and an identifier automatically generated

19 |
20 |
21 | 22 | 23 | 24 | 25 | {{end}} 26 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/element.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 | 3 | 4 |

Element {{.E.Name}}

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 |
FieldValue
Name, ItemID {{ .E.Name }}   {{ .E.ItemID }}
Description {{ .E.Description }}
Protocol, Endpoint {{ .E.Protocol }}   {{ .E.Endpoint }}
Tags {{ range .E.Tags }} 18 | {{ . }} 19 | {{end}}
22 | 23 |
24 | 25 |
26 |
27 | 28 |
Results
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | {{ range .RS }} 41 | 42 | 43 | 44 | 45 | 46 | 50 | 51 | 52 | {{end}} 53 | 54 |
RuleNameVerifiedAtResult
{{ .RuleName }}{{ epochToUTC .VerifiedAt }} 47 | {{ template "resultvalue.html" .Result }} 48 | 49 |
55 |
56 | 57 |
58 |
59 | 60 | 61 |
Claims
62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | {{ range .CS }} 74 | {{ if eq .BodyType "*ERROR"}} 75 | 76 | {{else}} 77 | 78 | {{end}} 79 | 80 | 81 | 82 | 83 | {{end}} 84 | 85 | 86 |
BodyTypeRequestedPolicy
{{ .BodyType }}{{ epochToUTC .Header.Timing.Requested }}{{ .Header.Policy.Name }}S
87 | 88 | 89 |
90 |
91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
Additional Attributes
99 | 100 | {{ if not .E.TPM2.Device }} 101 | {{ else }} 102 |
103 |
Trusted Platform Module 2.0 (TPM)
104 | {{ template "tpm2.html" .E.TPM2 }} 105 | {{ end }} 106 | 107 | 108 | {{ if not .E.UEFI.Eventlog }} 109 | {{ else }} 110 |
111 | 112 |
Unified Extensible Firmware Interface (UEFI)
113 | {{ template "uefi.html" .E.UEFI }} 114 | {{ end }} 115 | 116 | 117 | 118 | {{ if not .E.IMA.ASCIILog }} 119 | {{ else }} 120 |
121 | 122 |
Integrity Measurement Architecture (IMA)
123 | {{ template "ima.html" .E.IMA }} 124 | {{ end }} 125 | 126 | 127 | {{ if not .E.TXT.Log }} 128 | {{ else }} 129 |
130 | 131 |
Intel Trusted Execution Technology (TXT)
132 | {{ template "txt.html" .E.TXT }} 133 | {{ end }} 134 | 135 | {{ if not .E.Host.Arch }} 136 | {{ else }} 137 |
138 | 139 |
Host Information
140 | {{ template "hostinformation.html" .E.Host }} 141 | {{ end }} 142 | 143 |
144 | {{ .E }} 145 | 146 | {{end}} 147 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/elements.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Elements

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {{ range . }} 15 | {{ template "elementsummarylist.html" . }} 16 | {{end}} 17 | 18 |
NameDescriptionTagsProtocolEndpoint
19 | {{end}} 20 | 21 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/elementsummarylist.html: -------------------------------------------------------------------------------- 1 | {{define "elementsummarylist.html"}} 2 | {{ .Name }} 3 | {{ .Description }} 4 | {{ range .Tags }} 5 | {{ . }} 6 | {{end}} 7 | {{ .Protocol }} 8 | {{ .Endpoint }} 9 | {{end}} 10 | 11 | 12 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/ev.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Expected Value {{ .EV.Name }}

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
FieldValue
Name {{ .EV.Name }}
Description {{ .EV.Description }}
ItemID {{ .EV.ItemID }}
Element {{ .E.Name }} @ {{ .E.Endpoint }} {{ .E.Protocol }}
Policy {{ .P.Name }} {{ .P.Intent }}
EVS Parameters {{ template "genericList.html" .EV.EVS }}
24 | 25 | 26 | {{end}} 27 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/evs.html: -------------------------------------------------------------------------------- 1 | {{template "base" .}} 2 | {{define "content"}} 3 |

Expected Values

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{ range . }} 18 | 19 | 20 | {{ template "evsummarylist.html" . }} 21 | 22 | 23 | 24 | {{end}} 25 | 26 |
NameDescriptionElementEndpointPolicyIntent
27 | {{end}} 28 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/evsummarylist.html: -------------------------------------------------------------------------------- 1 | {{define "evsummarylist.html"}} 2 | {{ .EV.Name }} 3 | {{ .EV.Description }} 4 | {{ .E.Name }} 5 | {{ .E.Endpoint }} 6 | {{ .P.Name }} 7 | {{ .P.Intent }} 8 | 9 | {{end}} 10 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/genericList.html: -------------------------------------------------------------------------------- 1 | {{define "genericList.html"}} 2 | 3 | 4 | {{ range $key, $value := . }} 5 | 6 | {{ end }} 7 | 8 |
{{ $key }} {{ $value }}
9 | {{end}} 10 | 11 | 12 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/help.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |
3 |

There is not a lot of help in this version either...

4 |

sorry.

5 |
6 | 7 | {{end}} -------------------------------------------------------------------------------- /ga10/services/webui/templates/hostinformation.html: -------------------------------------------------------------------------------- 1 | {{define "hostinformation.html"}} 2 | 3 | 4 | 5 | 6 | 7 |
Hostname {{ .Hostname }}
OS / Arch {{ .OS }} {{ .Arch }}
8 | {{end}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/ima.html: -------------------------------------------------------------------------------- 1 | {{define "ima.html"}} 2 | 3 | 4 | 5 | 6 | 7 |
ASCII Log {{ .ASCIILog }}
8 | {{end}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/log.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Log

3 |

Showing {{ .Amount }} entries of {{ .Count }} for duration {{ .Duration }}

4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {{ range .LogEntries }} 17 | 18 | 19 | {{ if eq .Operation "startup/INIT"}} 20 | 21 | {{ else if eq .Channel "SYS"}} 22 | 23 | {{else}} 24 | 25 | {{end}} 26 | 27 | 28 | 29 | 46 | 47 | 48 | {{end}} 49 | 50 |
TimestampChannelOperationReferenceMessage
{{ epochToUTC .Timestamp }}{{ .Channel }}{{ .Operation }} 30 | {{ if eq .RefType "element" }} 31 | element 32 | {{ else if eq .RefType "policy" }} 33 | policy 34 | {{ else if eq .RefType "expectedvalue" }} 35 | expectedvalue 36 | {{ else if eq .RefType "claim" }} 37 | claim 38 | {{ else if eq .RefType "result" }} 39 | result 40 | {{ else if eq .RefType "session" }} 41 | session 42 | {{ else }} 43 | {{ .RefType }} 44 | {{ end }} 45 | {{ .Message }}
51 | {{end}} 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/opaqueobject.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Opaque Object

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
FieldValue
Short Description{{ .ShortDescription }}
Value{{ .Value }}
Type {{ .Type }}
Long Description{{ .LongDescription }}
18 | 19 | 20 | 21 | {{end}} 22 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/opaqueobjects.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Opaque Objects

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{ range . }} 14 | 15 | 16 | 17 | 18 | {{end}} 19 | 20 |
ValueTypeShort Description
{{ .Value }} {{ .Type }} {{ .ShortDescription }}
21 | {{end}} 22 | 23 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/policies.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Policies

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{ range . }} 13 | {{ template "policysummarylist.html" . }} 14 | {{end}} 15 | 16 |
NameIntentDescription
17 | {{end}} 18 | 19 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/policy.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Policy: {{ .Name }}

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
FieldValue
Name {{ .Name }}
Description {{ .Description }}
ItemID {{ .ItemID }}
Intent {{ .Intent }}
Parameters {{ template "genericList.html" .Parameters }}
21 | 22 | 23 | {{end}} 24 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/policysummarylist.html: -------------------------------------------------------------------------------- 1 | {{define "policysummarylist.html"}} 2 | {{ .Name }} 3 | {{ .Intent }} 4 | {{ .Description }} 5 | {{end}} 6 | 7 | 8 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/protocols.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Protocols

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{ range . }} 13 | 14 | 15 | 20 | {{end}} 21 | 22 |
NameDescriptionSupported Intents
{{ .Name }} {{ .Description }} 16 | {{ range .Intents }} 17 | {{ . }} 18 | {{end}} 19 |
23 | {{end}} 24 | 25 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/result.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Result

3 | 4 |
Element Information
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
FieldValue
Rule Name {{ .R.RuleName }}
VerifiedAt {{ epochToUTC .R.VerifiedAt }}
Result {{ template "resultvalue.html" .R.Result }}
Expected Value {{ .R.EV_Name }}
Element {{ .R.EVEName }}
Policy {{ .R.EVPName }}
Claim {{ .R.ClaimID }}
Session {{ .R.SessionID }}
Message {{ .R.Message }}
24 | 25 | 26 | 27 |
Footer
28 | 29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
FieldValue
Hash {{ encodeAsHexString .R.Footer.Hash }}
Signature {{ encodeAsHexString .R.Footer.Signature }}
45 | 46 |
47 |
48 |
49 | 50 | {{end}} 51 | 52 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/results.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Results

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {{ range . }} 16 | 17 | 18 | 19 | 20 | 21 | 25 | {{ if not .EV_Name}} 26 | 27 | {{ else }} 28 | 29 | {{ end }} 30 | 31 | 32 | 33 | 34 | {{end}} 35 | 36 |
RuleNameVerifiedAtResultEVLinksMessage
{{ .RuleName }}{{ epochToUTC .VerifiedAt }} 22 | {{ template "resultvalue.html" .Result }} 23 | 24 | -{{ .EV_Name }} ( {{ .EVEName }} | {{ .EVPName }} )C | S {{ .Message }}
37 | {{end}} 38 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/resultvalue.html: -------------------------------------------------------------------------------- 1 | {{define "resultvalue.html"}} 2 | {{ if eq . 0}} 3 | Pass 4 | {{else if eq . 9001}} 5 | Fail 6 | 7 | {{else if eq . 9010}} 8 | Verify Call Failure 9 | {{else if eq . 9098}} 10 | Verify Claim Error 11 | {{else if eq . 9099}} 12 | No Result 13 | 14 | {{else if eq . 9997}} 15 | Missing Expected Value 16 | {{else if eq . 9998}} 17 | Rule Call Failure 18 | {{else if eq . 9999}} 19 | Unset Result Value 20 | 21 | {{else}} 22 | Unknown Error 23 | {{end}} 24 | {{end}} 25 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/rules.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Rules

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{ range . }} 14 | 15 | 16 | 24 | {{end}} 25 | 26 |
Name Description
{{ .Name }} 17 | {{ if eq .NeedsEV true}} 18 | EV Required 19 | {{else}} 20 | - 21 | {{end}} 22 | 23 | {{ .Description }}
27 | {{end}} 28 | 29 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/scraps: -------------------------------------------------------------------------------- 1 | 2 | 46 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/sessions.html: -------------------------------------------------------------------------------- 1 | {{define "content"}} 2 |

Sessions

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{ range . }} 14 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | {{end}} 28 | 29 |
OpenedClosedMessage# Claims/Results
{{ epochToUTC .Timing.Opened }} 17 | {{ if eq .Timing.Closed 0 }} 18 | session open 19 | {{ else }} 20 | {{ epochToUTC .Timing.Closed }} 21 | {{ end }} 22 | {{ .Message }}{{ len .ClaimList }} / {{ len .ResultList }}
30 | {{end}} 31 | 32 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/tpm2.html: -------------------------------------------------------------------------------- 1 | {{define "tpm2.html"}} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
TPM Device {{ .Device }}
EK Certificate NVRAM Handle {{ .EKCertHandle }}
Endorsement Key {{ template "tpm2key.html" .EK }}
Atteststion Key {{ template "tpm2key.html" .AK }}
13 | {{end}} 14 | 15 | 16 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/tpm2key.html: -------------------------------------------------------------------------------- 1 | {{define "tpm2key.html"}} 2 | 3 | 4 | 5 | 6 | 7 |
Handle {{ .Handle }}
Public {{ .Public }}
8 | {{end}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/txt.html: -------------------------------------------------------------------------------- 1 | {{define "txt.html"}} 2 | 3 | 4 | 5 | 6 |
TXT-Stat Log {{ .Log }}
7 | {{end}} 8 | 9 | 10 | -------------------------------------------------------------------------------- /ga10/services/webui/templates/uefi.html: -------------------------------------------------------------------------------- 1 | {{define "uefi.html"}} 2 | 3 | 4 | 5 | 6 | 7 |
Eventlog {{ .Eventlog }}
8 | {{end}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /ga10/services/x3270/initx3270.go: -------------------------------------------------------------------------------- 1 | package x3270 2 | 3 | import( 4 | _ "net/http" 5 | 6 | "os" 7 | "net" 8 | "fmt" 9 | 10 | "a10/configuration" 11 | "a10/logging" 12 | 13 | "github.com/racingmars/go3270" 14 | 15 | ) 16 | 17 | 18 | 19 | 20 | func init() { 21 | // put the go3270 library in debug mode 22 | go3270.Debug = os.Stderr 23 | } 24 | 25 | func StartX3270() { 26 | 27 | //get configuration data 28 | port := configuration.ConfigData.X3270.Port 29 | //crt := configuration.ConfigData.Rest.Crt 30 | //key:= configuration.ConfigData.Rest.Key 31 | //usehttp := configuration.ConfigData.Rest.UseHTTP 32 | 33 | //start the server 34 | ln, err := net.Listen("tcp", ":"+port) 35 | if err != nil { 36 | logging.MakeLogEntry("SYS","startup",configuration.ConfigData.System.Name,"GA10","X3270 service failed to start.") 37 | fmt.Printf("X3270 failed to start service") 38 | panic(err) 39 | } 40 | 41 | logging.MakeLogEntry("SYS","startup",configuration.ConfigData.System.Name,"GA10","X3270 service started.") 42 | fmt.Printf("X3270 service listening on port %v\n",port) 43 | for { 44 | conn, err := ln.Accept() 45 | if err != nil { 46 | logging.MakeLogEntry("SYS","x3270",configuration.ConfigData.System.Name,"GA10","X3270 failed to accept connnection") 47 | fmt.Printf("X3270 failed to accept connnection") 48 | panic(err) 49 | } 50 | go handle(conn) 51 | } 52 | 53 | } 54 | 55 | // handle is the handler for individual user connections. 56 | func handle(conn net.Conn) { 57 | defer conn.Close() 58 | 59 | // Always begin new connection by negotiating the telnet options 60 | go3270.NegotiateTelnet(conn) 61 | 62 | fieldValues := make(map[string]string) 63 | 64 | 65 | response, err := go3270.HandleScreen( 66 | titlescreen, // the screen to display 67 | titlescreenrules, // the rules to enforce 68 | fieldValues, // any field values we wish to supply 69 | []go3270.AID{go3270.AIDEnter}, // the AID keys we support 70 | []go3270.AID{go3270.AIDPF3}, // keys that are "exit" keys 71 | "errormsg", // the field to write error message into 72 | 4, 20, // the row and column to place the cursor 73 | conn) 74 | if err != nil { 75 | fmt.Printf("X3270 handle screen error %w",err) 76 | fmt.Println(err) 77 | return 78 | } 79 | 80 | fmt.Printf("Connection closed %v \n",response) 81 | } -------------------------------------------------------------------------------- /ga10/services/x3270/screenrules.go: -------------------------------------------------------------------------------- 1 | package x3270 2 | 3 | import ( 4 | "github.com/racingmars/go3270" 5 | ) 6 | 7 | var titlescreenrules = go3270.Rules{ 8 | "option": {Validator: go3270.NonBlank, MustChange: true}, 9 | 10 | } -------------------------------------------------------------------------------- /ga10/services/x3270/screens.go: -------------------------------------------------------------------------------- 1 | package x3270 2 | 3 | import ( 4 | "github.com/racingmars/go3270" 5 | ) 6 | 7 | var titlescreen = go3270.Screen{ 8 | {Row: 2, Col: 10, Intense: false, Content: "GA10 - Primary Menu"}, 9 | 10 | {Row: 4, Col: 2, Intense: false, Content: "Option ==>"}, 11 | 12 | {Row: 6, Col: 2, Intense: false, Content: "1. List elements"}, 13 | {Row: 7, Col: 2, Intense: false, Content: "2. List sessions"}, 14 | {Row: 8, Col: 2, Intense: false, Content: "3. Attest"}, 15 | 16 | {Row: 4, Col: 14, Highlighting: go3270.Underscore, Write: true, Name: "option"}, 17 | {Row: 4, Col: 18 }, 18 | 19 | } 20 | -------------------------------------------------------------------------------- /ga10/structures/claims.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | 4 | 5 | type Claim struct { 6 | ItemID string `json:"itemid",bson:"itemid"` 7 | BodyType string `json:"bodytype",bson:"bodytype"` 8 | Header ClaimHeader `json:"header",bson:"header"` 9 | Body map[string]interface{} `json:"body",bson:"body"` 10 | Footer ClaimFooter `json:"footer",bson:"footer"` 11 | } 12 | 13 | 14 | type ClaimHeader struct { 15 | Element Element `json:"element",bson:"element"` 16 | Policy Policy `json:"policy",bson:"policy"` 17 | Session Session `json:"session",bson:"session"` 18 | Timing Timing `json:"timing",bson:"timing"` 19 | AdditionalParameters map[string]interface{} `json:"aps",bson:"aps"` 20 | CallParameters map[string]interface{} `json:"cps",bson:"cps"` 21 | 22 | } 23 | 24 | type Timing struct { 25 | Requested Timestamp `json:"requested",bson:"requested"` 26 | Received Timestamp `json:"received",bson:"received"` 27 | } 28 | 29 | type ClaimFooter struct { 30 | Hash []byte `json:"hash",bson:"hash"` 31 | Signature []byte `json:"signature",bson:"signature"` 32 | } 33 | 34 | const CLAIMERROR = "*ERROR" -------------------------------------------------------------------------------- /ga10/structures/common.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | type ID struct { 4 | ItemID string `json:"itemid",bson:"itemid"` 5 | } 6 | -------------------------------------------------------------------------------- /ga10/structures/elements.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | type Element struct { 4 | ItemID string `json:"itemid,omitempty",bson:"itemid,omitempty"` 5 | Name string `json:"name",bson:"name"` 6 | Description string `json:"description",bson:"description"` 7 | Endpoint string `json:"endpoint",bson:"endpoint"` 8 | Protocol string `json:"protocol",bson:"protocol"` 9 | Tags []string `json:"tags",bson:"tags"` 10 | 11 | Sshkey SSHKEY `json:"sshkey,omitempty",bson:"sshkey,omitempty"` 12 | TPM2 TPM2 `json:"tpm2,omitempty",bson:"tpm2,omitempty"` 13 | UEFI UEFI `json:"uefi,omitempty",bson:"uefi,omitempty"` 14 | IMA IMA `json:"ima,omitempty",bson:"ima,omitempty"` 15 | TXT TXT `json:"txt,omitempty",bson:"txt,omitempty"` 16 | Host HostMachine `json:"host,omitempty",bson:"host,omitempty"` 17 | MRCoordinator MRCoordinator `json:"mrcoordinator,omitempty" bson:"mrcoordinator,omitempty"` 18 | MRMarbleInstance MRMarbleInstance `json:"mrmarbleinstance,omitempty" bson:"mrmarbleinstance,omitempty"` 19 | } 20 | 21 | type HostMachine struct { 22 | OS string `json:"os",bson:"os"` 23 | Arch string `json:"arch",bson:"arch"` 24 | Hostname string `json:"hostname",bson:"hostname"` 25 | } 26 | 27 | type SSHKEY struct { 28 | Key string `json:"key",bson:"key"` 29 | Timeout int16 `json:"timeout",bson:"timeout"` 30 | Username string `json:"username",bson:"username"` 31 | } 32 | 33 | type UEFI struct { 34 | Eventlog string `json:"eventlog",bson:"eventlog"` 35 | } 36 | 37 | type IMA struct { 38 | ASCIILog string `json:"asciilog",bson:"asciilog"` 39 | } 40 | 41 | type TXT struct { 42 | Log string `json:"log",bson:"log"` 43 | } 44 | 45 | type TPM2 struct { 46 | Device string `json:"device",bson:"device"` 47 | EKCertHandle string `json:"ekcerthandle",bson:"ekcerthandle"` 48 | EK TPMKey `json:"ek",bson:"ek"` 49 | AK TPMKey `json:"ak",bson:"ak"` 50 | } 51 | 52 | type TPMKey struct { 53 | Handle string `json:"handle",bson:"handle"` 54 | // Public portion of the key marshalled as TPM2BPublic 55 | Public string `json:"public",bson:"public"` 56 | } 57 | 58 | type MRCoordinator struct { 59 | Certs []string `json:"certs" bson:"certs"` 60 | } 61 | 62 | type MRMarbleInstance struct { 63 | ExpectedNonce string `json:"expectednonce" bson:"expectednonce"` 64 | RequestData string `json:"requestdata" bson:"requestdata"` 65 | RequestSignature string `json:"requestsignature" bson:"requestsignature"` 66 | } 67 | -------------------------------------------------------------------------------- /ga10/structures/logs.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | 4 | 5 | type LogEntry struct { 6 | ItemID string `json:"itemid",bson:"itemid"` 7 | Timestamp Timestamp `json:"timestamp",bson:"timestamp"` 8 | Channel string `json:"channel",bson:"channel"` 9 | Operation string `json:"operation",bson:"operation"` 10 | RefID string `json:"refid",bson:"refid"` 11 | RefType string `json:"reftype",bson:"reftype"` 12 | Message string `json:"message",bson:"message"` 13 | Hash []byte `json:"hash",bson:"hash"` 14 | } 15 | -------------------------------------------------------------------------------- /ga10/structures/opaqueobjects.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | type OpaqueObject struct { 4 | Value string `json:"value",bson:"value"` 5 | Type string `json:"type",bson:"type"` 6 | ShortDescription string `json:"shortdescription",bson:"shortdescription"` 7 | LongDescription string `json:"longdescription",bson:"longdescription"` 8 | } 9 | -------------------------------------------------------------------------------- /ga10/structures/policies.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | type Policy struct { 4 | ItemID string `json:"itemid",bson:"itemid"` 5 | Name string `json:"name",bson:"name"` 6 | Description string `json:"description",bson:"description"` 7 | Intent string `json:"intent",bson:"intent"` 8 | Parameters map[string]interface{} `json:"parameters",bson:"parameters"` 9 | } 10 | -------------------------------------------------------------------------------- /ga10/structures/protocols.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | //This is the type of the protocol functions 4 | // 5 | // In useage it takes the element, policy, session and a "json" structure of parameters 6 | // Return is "json" and a string containing any error messages 7 | type ProtocolCall func(Element, Policy, Session, map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) 8 | 9 | 10 | type Protocol struct { 11 | Name string 12 | Description string 13 | CallFunction ProtocolCall 14 | Intents []string 15 | } 16 | 17 | -------------------------------------------------------------------------------- /ga10/structures/results.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | type ResultValue int 4 | 5 | const ( 6 | Success ResultValue = 0 7 | Fail = 9001 8 | 9 | VerifyCallFailure = 9010 10 | VerifyClaimErrorAttempt = 9098 11 | NoResult = 9099 12 | 13 | MissingExpectedValue = 9997 14 | RuleCallFailure = 9998 15 | UnsetResultValue = 9999 16 | ) 17 | 18 | type Result struct { 19 | ItemID string `json:"itemid",bson:"itemid"` 20 | ClaimID string `json:"claimid",bson:"claimid"` 21 | ClaimFooter ClaimFooter `json:"claimfooter",bson:"claimfooter"` 22 | Session Session `json:"session",bson:"session"` 23 | ElementID string `json:"elementid",bson:"elementid"` 24 | ExpectedValue ExpectedValue `json:"expectedvalue",bson:"expectedvalue"` 25 | Parameters map[string]interface{} `json:"parameters",bson:"parameters"` 26 | Message string `json:"message",bson:"message"` 27 | RuleName string `json:"rulename",bson:"rulename"` 28 | VerifiedAt Timestamp `json:"verifiedat",bson:"verifiedat"` 29 | Result ResultValue `json:"result",bson:"result"` 30 | Footer ResultFooter `json:"footer",bson:"footer"` 31 | } 32 | 33 | type ResultFooter struct { 34 | Hash []byte `json:"hash",bson:"hash"` 35 | Signature []byte `json:"signature",bson:"signature"` 36 | } 37 | -------------------------------------------------------------------------------- /ga10/structures/rules.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | //This is the type of the protocol functions 4 | // 5 | // In useage it takes the element, policy, session and a "json" structure of parameters 6 | // Return is "json" and a string containing a message from the rule and error in case everything fails 7 | type RuleCall func(Claim, string, ExpectedValue, Session, map[string]interface{}) (ResultValue, string, error) 8 | 9 | type Rule struct { 10 | Name string 11 | Description string 12 | CallFunction RuleCall 13 | NeedsEV bool 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /ga10/structures/sessions.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | 4 | type Session struct { 5 | ItemID string `json:"itemid",bson:"itemid"` 6 | Timing SessionTiming `json:"timing",bson:"timing"` 7 | 8 | ClaimList []string `json:"claimlist",bson:"claimlist"` 9 | ResultList []string `json:"resultlist",bson:"resultlist"` 10 | 11 | Message string `json:"message",bson:"message"` 12 | 13 | Footer SessionFooter `json:"footer",bson:"footer"` 14 | } 15 | 16 | 17 | type SessionSummary struct { 18 | ItemID string `json:"itemid",bson:"itemid"` 19 | Timing SessionTiming `json:"timing",bson:"timing"` 20 | } 21 | 22 | 23 | type SessionTiming struct { 24 | Opened Timestamp `json:"opened",bson:"opened"` 25 | Closed Timestamp `json:"closed",bson:"closed"` 26 | } 27 | 28 | 29 | type SessionFooter struct { 30 | Hash []byte `json:"hash",bson:"hash"` 31 | Signature []byte `json:"signature",bson:"signature"` 32 | } 33 | -------------------------------------------------------------------------------- /ga10/structures/types.go: -------------------------------------------------------------------------------- 1 | package structures 2 | 3 | type Timestamp int64 4 | -------------------------------------------------------------------------------- /ga10/temporary.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID+TCCAuGgAwIBAgIUVJZap9c3I9vnPWzjuCdr2HzMn58wDQYJKoZIhvcNAQEL 3 | BQAwgYsxCzAJBgNVBAYTAkZJMRAwDgYDVQQIDAdVdXNpbWFhMQ4wDAYDVQQHDAVT 4 | aXBvbzESMBAGA1UECgwJQ2VmZnlsT3BpMQwwCgYDVQQLDANSJkQxDDAKBgNVBAMM 5 | A0lhbjEqMCgGCSqGSIb3DQEJARYbaWFuLmp1c3Rpbi5vbGl2ZXJAZ21haWwuY29t 6 | MB4XDTIzMDQyNDE2NDEyM1oXDTI0MDQyMzE2NDEyM1owgYsxCzAJBgNVBAYTAkZJ 7 | MRAwDgYDVQQIDAdVdXNpbWFhMQ4wDAYDVQQHDAVTaXBvbzESMBAGA1UECgwJQ2Vm 8 | ZnlsT3BpMQwwCgYDVQQLDANSJkQxDDAKBgNVBAMMA0lhbjEqMCgGCSqGSIb3DQEJ 9 | ARYbaWFuLmp1c3Rpbi5vbGl2ZXJAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEF 10 | AAOCAQ8AMIIBCgKCAQEAnYeTyopKf82aGAtACj3GFXBDyAqnOWz3t5P8x7mhU6TW 11 | /+RKbKIpV9/Gytg0hQOsXf5izjOqwu92RJA08W0iO6J/GNFEuYg3tf3MYtFmDZL7 12 | DtHicRY+apSgrv4NtpTezW0DHFdyLHK0RL32Fgkb9JRHfQdssRmymKu8PvPxyFw7 13 | HbD7MurORiGycl/oVdrRhws7lMF/kLuK+ksh3G6M/+sF/4HCtAJ37aeXRAnudktB 14 | RelkBd80HKebsbtPkwJrF1g5VpVBDgJVx28MfRrGLotiKwmAp1nVha6JcGZ6y3Sl 15 | BYTW96/g1QlxOC7tYef0QyyGDeAhIivSwlzuGZ3EzQIDAQABo1MwUTAdBgNVHQ4E 16 | FgQUhMNzN/omyGgTvG5jqDWtFN1G/lkwHwYDVR0jBBgwFoAUhMNzN/omyGgTvG5j 17 | qDWtFN1G/lkwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAmB24 18 | b+ST3ds4pfdiAB6Xfenkk3Fo9cg4hDA9v1nQvXe49x9ZMq5yZ9tkOIWtI0y2nCky 19 | qUGbU08EuZmLyq7ReurRg2nMLi/M+xMJmaCzMMg8vQPMwcAy/EsDgVUS66rbWMYn 20 | VA/zLbjkNAXPzxYzVTSKVdw4loNLagoOkCZRYotA5w9LlmcC/5yxX9wJxb/K7CD7 21 | HPovpR1alU2J5vAbjmo/TAjRFzkt2pQ8kqjAmdWjJb/zIJWwv/s62obb/Ye9kZy4 22 | 40CejuNxsYIvkMyeNAAs6psDO/eEMQITvtaMakczM6qQpdX6yYdWnUOvvjOfu6YA 23 | k7nQ2CE2vEAiLhxZIQ== 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /ga10/temporary.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdh5PKikp/zZoY 3 | C0AKPcYVcEPICqc5bPe3k/zHuaFTpNb/5EpsoilX38bK2DSFA6xd/mLOM6rC73ZE 4 | kDTxbSI7on8Y0US5iDe1/cxi0WYNkvsO0eJxFj5qlKCu/g22lN7NbQMcV3IscrRE 5 | vfYWCRv0lEd9B2yxGbKYq7w+8/HIXDsdsPsy6s5GIbJyX+hV2tGHCzuUwX+Qu4r6 6 | SyHcboz/6wX/gcK0Anftp5dECe52S0FF6WQF3zQcp5uxu0+TAmsXWDlWlUEOAlXH 7 | bwx9GsYui2IrCYCnWdWFrolwZnrLdKUFhNb3r+DVCXE4Lu1h5/RDLIYN4CEiK9LC 8 | XO4ZncTNAgMBAAECggEABlx/uNmdyYxtcRQfOWqmMZ5vdkgL2bNPS5AD0LLr01tg 9 | PUQkRz/DKKPGPNG/STHNR5xqtAX9GtMdtQYXxToRfFQDCucEffOEwGon00O+ecTa 10 | M46BNOzfh2FKHdbvidR4LNZ+ninf1/Cn2/DJ27jxco58Vo2ys3IktqqUtvwV4u/a 11 | Tozfc5BWlVd2eYqwv8MyhZPpPxcArC1vPH2os/1/Q/qe8IpCOBHy12SN7Nje+l3p 12 | LYRLHm3rHhKPwHIEd05d5S3BZ0u3Eea20hXAynT2483XaLj1QpImRRZ4O5H0RRRE 13 | apRU7hPlqD8kpD7g6kbkiMCJUOp2Q2NbzfPVH7hlFwKBgQDQKOnABlG5InHPE+su 14 | I1AlvGIThFPbKZEH4MSA3nNEeyqV2P7eRadZexJdF8BAS8yqp73ZbbqFeAkMtL2/ 15 | gc4grOovr4BKy8S3w8utd82dqwD7dUxY+DcP57rogdz7Z82R+RpUwksitv8K1nDM 16 | JGo7WvDUDxQqnRs29WwFb+e9owKBgQDBu9WYeleUwl7krKW9+XmqzDcHwXik6udv 17 | 591IFNbW0B3XGweI18bvTmpYK1cYNYhamloawEiERofX+LVQGKsz33XdcP9a/k7E 18 | ADJy+begSjRvQ7SML3V+KGZSPKE2Wo5ohpBgy+ytFCUb0APC0K/Mk/kjLQHr/ZSg 19 | 5bDp3fG6zwKBgQCoe4T/JN4+v+9oEZI4bOKxOHIVo/SPnmxB+R5zxBl+I0bLtLBN 20 | zgju9xtc+B1mrTOCKXUTqKng39BLVXuDpxflALAoWp+3aojVyIdx51cot8F6xm0+ 21 | UeGXYRO6n2nynwkXjo1Ob1iLR5zU886mnQ7S7f+hVHcZKsJdUHXXTMVAiwKBgDtU 22 | MJdfcA7Ib5MMJD3HdrENlRS09SNcJMAqe6Olbh2e4mSLjIUlv3BtzTdvHl71lepZ 23 | NprWo96OUu+a5LvAsj1Sg5/rCOhu1ORFQy3et5NI5kHktBfyOMMH0D4C/0PL+6ya 24 | +QALs1FVx/96doxkqFG4RyW0lNAWejvD26fjJjIVAoGAeP9pJPFIGFUpUwKTVgsJ 25 | cfm082bJsRpBvRWHhDvJA8nliY1XoTGzoproNxCeZLywkKREflGw2d9AeYgCo8OD 26 | z16VvR/B13l0Dh4fYQS7wGkGEJ2+LcKlEZ+lCWbrFNWHre8vZ9/capxB6PrPn10R 27 | N/cWWNE1DVBVVxu/83lsAk0= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /ga10/tests/exampledatabase/elements.json: -------------------------------------------------------------------------------- 1 | {"_id":{"$oid":"645277d5799325c3a0afaffb"},"itemid":"c7219a2b-7d02-4c1f-bad7-50c4d3b2cd2a","name":"WorkLaptopLinux","description":"Main work Linux laptop, with Cofiwch Dryweryn sticker on the back.","protocol":"A10HTTPRESTv2","endpoint":"http://192.168.1.218:8530","tags":["x86","linux","work"],"uefi":{"eventlog":"/sys/kernel/security/tpm0/binary_bios_measurements"},"ima":{"asciilog":"/sys/kernel/security/ima/ascii_runtime_measurements"},"tpm2":{"device":"/dev/tpmrm0","ek":{"handle":"0x810100EE","public":"aaa","name":"111"},"ak":{"handle":"0x810100AA","public":"bbb","name":"222"}}} 2 | {"_id":{"$oid":"645277d809d1d2ee1a672a84"},"itemid":"765e0188-a609-49c0-bf61-3825849413cd","name":"SensorPi","description":"Pi for running the sensor aggregation.","protocol":"A10HTTPRESTv2","endpoint":"http://192.168.1.111:8530","tags":["pi","linux","home"],"tpm2":{"device":"/dev/tpm0","ek":{"handle":"0x810100EE","public":"aaa","name":"111"},"ak":{"handle":"0x810100AA","public":"bbb","name":"222"}}} 3 | -------------------------------------------------------------------------------- /ga10/tests/exampledatabase/expectedvalues.json: -------------------------------------------------------------------------------- 1 | {"_id":{"$oid":"645a3fe44d2e1199e6183a1e"},"itemid":"d4b76ce1-2b56-4346-aa11-546ea412d1e5","name":"Work laptop firmware","description":"Firmware values, specifically PCR0,2,7 for work laptop","elementID":"c7219a2b-7d02-4c1f-bad7-50c4d3b2cd2a","policyID":"6770b5b9-d0ea-4f8b-817f-cab1bf8169c0","evs":{"attestedValue":"lR+zAH+TVf7g+QTNDVs9J0hD+VcbYNthM1RUQ2nfrsY=","firmwareVersion":"19984793217276456"}} 2 | {"_id":{"$oid":"645a76bf9b0597b56a39e98e"},"itemid":"fbe49635-e9e1-4f9a-b26b-4ca8401d0959","name":"Raspberru Pi firmware","description":"Firmware values, specifically PCR0,2,7 for work laptop","elementID":"765e0188-a609-49c0-bf61-3825849413cd","pid":"ba64f197-0eb3-4f3f-a74d-a9a8e0a3f17d","policyID":"6770b5b9-d0ea-4f8b-817f-cab1bf8169c0","evs":{"attestedValue":"lR+zAH+TVf7g+QTNDVs9J0hD+VcbYNthM1RUQ2nfrsY=","firmwareVersion":"19984793217276456"}} 3 | -------------------------------------------------------------------------------- /ga10/tests/exampledatabase/policies.json: -------------------------------------------------------------------------------- 1 | {"_id":{"$oid":"64501ba6090571d49e0ab35d"},"itemid":"6770b5b9-d0ea-4f8b-817f-cab1bf8169c0","name":"testPolicy","description":"This is a test policy for tpm2/quote","intent":"tpm2/quote","parameters":{"pcrSelection":"0,2,7","bank":"sha256"}} 2 | {"_id":{"$oid":"64501bb9090571d49e0ab35e"},"itemid":"ba64f197-0eb3-4f3f-a74d-a9a8e0a3f17d","name":"testPolicy","description":"This is a test policy for tpm2/pcrs","intent":"tpm2/pcrs","parameters":{}} 3 | {"_id":{"$oid":"64501bc9090571d49e0ab35f"},"itemid":"e7c5d901-3caa-4542-8660-7054560198e1","name":"testPolicy","description":"This is a test policy for uefi/eventlog","intent":"uefi/eventlog","parameters":{}} 4 | {"_id":{"$oid":"64501bd8090571d49e0ab360"},"itemid":" 8aa82519-16f0-4418-83e2-6e9e6edbcdc6","name":"testPolicy","description":"This is a test policy for null/null","intent":"null/null","parameters":{}} 5 | {"_id":{"$oid":"645a63ec9b0597b56a39e986"},"itemid":"9a74825f-f780-4eec-9b20-646ba924857a","name":"SystemInfo","description":"This retrieves the system info for a given device","intent":"sys/info","parameters":{}} 6 | {"_id":{"$oid":"645a64729b0597b56a39e988"},"itemid":"f147fbd9-af7e-46f6-a8f8-3b0734918743","name":"IMAlog","description":"This returns the Linux IMA ASCII Log","intent":"ima/asciilog","parameters":{}} 7 | -------------------------------------------------------------------------------- /ga10/tests/p11test/p.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "reflect" 6 | 7 | "github.com/miekg/pkcs11/p11" 8 | "github.com/miekg/pkcs11" 9 | 10 | ) 11 | 12 | 13 | func main() { 14 | fmt.Println("Starting") 15 | 16 | module,_ := p11.OpenModule("/usr/lib/x86_64-linux-gnu/pkcs11/yubihsm_pkcs11.so") 17 | //module,_ := p11.OpenModule("/usr/local/lib/softhsm/libsofthsm2.so") 18 | 19 | 20 | 21 | slots,_ := module.Slots() 22 | fmt.Printf("Slots %v\n",slots) 23 | 24 | session,_ := slots[0].OpenSession() 25 | fmt.Printf("Session %v\n",session) 26 | 27 | //err := session.Login("1234") 28 | err := session.Login("0001password") 29 | 30 | fmt.Printf("Login error %v\n",err) 31 | 32 | objects,err := session.FindObjects(nil) 33 | fmt.Printf("Number of objects %v\n",len(objects)) 34 | 35 | fmt.Printf("All objects\n") 36 | for i,v := range objects { 37 | l,_ := v.Label() 38 | cka,_ := v.Value() 39 | attrpublic,_ := v.Attribute(pkcs11.CKO_PUBLIC_KEY) 40 | attrprivate,_ := v.Attribute(pkcs11.CKO_PRIVATE_KEY) 41 | 42 | fmt.Printf("#%v label is %v, CKA %v PUB %v, PRIV %v\n",i,l,cka,attrpublic,string(attrprivate)) 43 | } 44 | 45 | 46 | template := []*pkcs11.Attribute{ 47 | pkcs11.NewAttribute(pkcs11.CKA_LABEL, "asymkey"), 48 | //pkcs11.NewAttribute(pkcs11.CKA_LABEL, "fred"), 49 | } 50 | fmt.Printf("\nGetting attributes for template %v\n",template) 51 | 52 | filteredobjects,err := session.FindObjects(template) 53 | fmt.Printf("Private key is %v\n",filteredobjects) 54 | for i,v := range filteredobjects { 55 | l,_ := v.Label() 56 | cka,_ := v.Value() 57 | attrpublic,_ := v.Attribute(pkcs11.CKO_PUBLIC_KEY) 58 | attrprivate,_ := v.Attribute(pkcs11.CKO_PRIVATE_KEY) 59 | 60 | fmt.Printf("#%v label is %v, CKA %v PUB %v, PRIV %v\n",i,l,cka,attrpublic,string(attrprivate)) 61 | } 62 | 63 | privateKey := p11.PrivateKey(filteredobjects[0]) 64 | publicKey := p11.PublicKey(filteredobjects[1]) 65 | fmt.Printf(" private key %v , %v \n",privateKey, publicKey) 66 | fmt.Printf(" types %v , %v \n", reflect.TypeOf(privateKey),reflect.TypeOf(publicKey)) 67 | 68 | plaintext := []byte("Croeso!") 69 | mechanism :=pkcs11.NewMechanism(pkcs11.CKM_RSA_PKCS,nil) 70 | 71 | enc,err := publicKey.Encrypt( *mechanism,plaintext) 72 | fmt.Printf(" plaintext %v, %v -> %v \n",err,plaintext, enc) 73 | 74 | dec,err := privateKey.Decrypt( *mechanism, enc) 75 | fmt.Printf(" %v -> %v \n",err,dec) 76 | 77 | 78 | 79 | fmt.Println("Logging out") 80 | session.Logout() 81 | fmt.Println("Closing") 82 | session.Close() 83 | fmt.Println("Done") 84 | 85 | } 86 | -------------------------------------------------------------------------------- /ga10/tests/p11test/yubihsm_pkcs11.conf: -------------------------------------------------------------------------------- 1 | connector=http://localhost:12345 -------------------------------------------------------------------------------- /ga10/tests/pkcs11test/go.mod: -------------------------------------------------------------------------------- 1 | module p 2 | 3 | go 1.20 4 | 5 | require github.com/miekg/pkcs11 v1.1.1 6 | -------------------------------------------------------------------------------- /ga10/tests/pkcs11test/go.sum: -------------------------------------------------------------------------------- 1 | github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= 2 | github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= 3 | -------------------------------------------------------------------------------- /ga10/tests/pkcs11test/p.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | 6 | "github.com/miekg/pkcs11" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("Starting") 11 | 12 | p := pkcs11.New("/usr/lib/x86_64-linux-gnu/pkcs11/yubihsm_pkcs11.so") 13 | 14 | //p := pkcs11.New("/usr/lib/x86_64-linux-gnu/pkcs11/gnome-keyring-pkcs11.so") 15 | 16 | 17 | fmt.Printf("PKCS11 module is %v\n",p) 18 | 19 | err := p.Initialize() 20 | fmt.Printf("PKCS11 initialisation is %v\n",err) 21 | 22 | defer p.Destroy() 23 | defer p.Finalize() 24 | 25 | slots, err := p.GetSlotList(true) 26 | fmt.Printf("err = %v , slots = %v\n",err,slots) 27 | 28 | fmt.Println("SLOTS =========================================") 29 | for i,v := range slots { 30 | slotinfo, err := p.GetSlotInfo(v) 31 | fmt.Printf("#%v err = %v, desc=%v,man=%v,flags=%v,hw=%v,fw=%v\n", i, err, slotinfo.SlotDescription, slotinfo.ManufacturerID,slotinfo.Flags,slotinfo.HardwareVersion,slotinfo.FirmwareVersion) 32 | } 33 | 34 | fmt.Println("TOKENS =========================================") 35 | for _,v := range slots { 36 | tokeninfo, err := p.GetTokenInfo(v) 37 | fmt.Printf("err = %v, info =%v\n", err, tokeninfo) 38 | } 39 | 40 | fmt.Println("MECHANISMS =========================================") 41 | mchs, err := p.GetMechanismList(slots[0]) 42 | fmt.Printf("err = %v, mchs =%v\n", err, mchs) 43 | 44 | 45 | 46 | 47 | fmt.Println("\nOpening Session") 48 | session, err := p.OpenSession(slots[0], pkcs11.CKF_SERIAL_SESSION) 49 | fmt.Printf("Session err %v session %v\n",err,session) 50 | 51 | fmt.Println("\nLogging In") 52 | err = p.Login(session, pkcs11.CKU_USER, "0001password") 53 | fmt.Printf("Login err %v \n",err) 54 | 55 | fmt.Println("\nFinding Objects") 56 | 57 | template := []*pkcs11.Attribute{ 58 | pkcs11.NewAttribute(pkcs11.CKA_LABEL, "rsa2048_ian"), 59 | pkcs11.NewAttribute(pkcs11.CKO_PRIVATE_KEY, nil), 60 | } 61 | 62 | if e := p.FindObjectsInit(session, template); e != nil { 63 | fmt.Printf("Failed FindObjectsInit") 64 | } 65 | 66 | objs, b, err := p.FindObjects(session,10) 67 | for i,oh := range objs { 68 | fmt.Printf("#%v , err=%v, bools=%v, objecthandle = %v %v\n",i,err,b,oh) 69 | 70 | ats := []*pkcs11.Attribute{ 71 | pkcs11.NewAttribute( pkcs11.CKA_LABEL, nil), 72 | } 73 | 74 | attr,err := p.GetAttributeValue(session, pkcs11.ObjectHandle(oh), ats) 75 | fmt.Printf(" +.... %v attr= %v \n",err,attr) 76 | 77 | //obj := pkcs11.ObjectHandle(oh) 78 | //fmt.Printf(" +---- %v",obj.Label()) 79 | } 80 | 81 | if e:=p.FindObjectsFinal(session); e != nil { 82 | fmt.Printf("Failed FindObjectsFinal") 83 | 84 | } 85 | 86 | 87 | 88 | 89 | fmt.Println("\nClosing THings") 90 | p.Logout(session) 91 | p.CloseSession(session) 92 | 93 | 94 | } -------------------------------------------------------------------------------- /ga10/tests/pkcs11test/yubihsm_pkcs11.conf: -------------------------------------------------------------------------------- 1 | connector=http://localhost:12345 -------------------------------------------------------------------------------- /ga10/tests/testscripts/attest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #work laptop and tpm2/quote policy 4 | #curl -X GET http://127.0.0.1:8520/element/c7219a2b-7d02-4c1f-bad7-50c4d3b2cd2a 5 | #curl -X GET http://127.0.0.1:8520/policy/6770b5b9-d0ea-4f8b-817f-cab1bf8169c0 6 | 7 | #open session 8 | osid="$( curl -s -X POST -H "Content-Type: application/json" http://127.0.0.1:8520/session | jq -r '.itemid' )" 9 | echo "Session opened: http://127.0.0.1:8520/session/$osid" 10 | 11 | #attest 12 | cid="$( curl -s -X POST -H "Content-Type: application/json" -d '{"eid":"c7219a2b-7d02-4c1f-bad7-50c4d3b2cd2a","pid":"6770b5b9-d0ea-4f8b-817f-cab1bf8169c0", "sid": "'"$osid"'", "parameters":{}}' http://127.0.0.1:8520/attest | jq -r '.itemid' )" 13 | echo "Claim is: http://127.0.0.1:8520/claim/$cid" 14 | 15 | #verify 16 | #rid="$( curl -s -X POST -H "Content-Type: application/json" -d '{"cid": ""$cid"", "sid": ""$osid"", "rule":"tpm2/firmware" 17 | #, "parameters":{}}' http://127.0.0.1:8520/verify | jq -r '.itemid' )" 18 | #echo "Result is: http://127.0.0.1:8520/result/$rid" 19 | 20 | #close session 21 | csid="$( curl -s -X DELETE -H "Content-Type: application/json" http://127.0.0.1:8520/session/""$osid"" | jq -r '.itemid' )" 22 | echo "Session closed: http://127.0.0.1:8520/session/$osid" 23 | -------------------------------------------------------------------------------- /ga10/tests/testscripts/get.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Gets" 4 | curl -X GET http://127.0.0.1:8520/elements 5 | curl -X GET http://127.0.0.1:8520/policies 6 | curl -X GET http://127.0.0.1:8520/expectedValues 7 | #curl -X GET http://127.0.0.1:8520/claims 8 | curl -X GET http://127.0.0.1:8520/results 9 | curl -X GET http://127.0.0.1:8520/hashes 10 | curl -X GET http://127.0.0.1:8520/protocols 11 | curl -X GET http://127.0.0.1:8520/rules 12 | 13 | echo "Get specifics" 14 | curl -X GET http://127.0.0.1:8520/element/c7219a2b-7d02-4c1f-bad7-50c4d3b2cd2a 15 | curl -X GET http://127.0.0.1:8520/policy/6770b5b9-d0ea-4f8b-817f-cab1bf8169c0 16 | curl -X GET http://127.0.0.1:8520/protocol/A10HTTPRESTv2 17 | 18 | echo "Get stuff that does not exist" 19 | curl -X GET http://127.0.0.1:8520/element/foobar 20 | curl -X GET http://127.0.0.1:8520/policy/barfoo 21 | curl -X GET http://127.0.0.1:8520/protocol/foobar -------------------------------------------------------------------------------- /ga10/utilities/hashes.go: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | import( 4 | "encoding/gob" 5 | "fmt" 6 | "bytes" 7 | "crypto/sha256" 8 | ) 9 | 10 | func init(){ 11 | 12 | gob.Register([]interface{}{}) 13 | gob.Register(map[string]interface{}{}) 14 | 15 | } 16 | 17 | func MakeSHA256(i any) ([]uint8,error) { 18 | 19 | var b bytes.Buffer 20 | 21 | e := gob.NewEncoder(&b) 22 | if err := e.Encode(i); err != nil { 23 | return []uint8{},fmt.Errorf("hash encoding Failed with error %w", err) 24 | } 25 | 26 | h := sha256.New() 27 | h.Write(b.Bytes()) 28 | digest := h.Sum(nil) 29 | 30 | return digest,nil 31 | } -------------------------------------------------------------------------------- /ga10/utilities/identifiers.go: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | import( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | func MakeID() string { 8 | return uuid.New().String() 9 | } -------------------------------------------------------------------------------- /ga10/utilities/timestamps.go: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | import( 4 | "time" 5 | //"fmt" 6 | 7 | "a10/structures" 8 | ) 9 | 10 | 11 | //makeTimestamp generates the number of nanoseconds since Unix Epoch in UTC. 12 | func MakeTimestamp() structures.Timestamp { 13 | //t := structures.Timestamp(fmt.Sprintf("%d",time.Now().UnixNano())) 14 | t := structures.Timestamp(time.Now().UnixNano()) 15 | 16 | return t 17 | } 18 | 19 | //returns the timestampe value for some value, eg: 2h30m 20 | func TimeStampHoursAgo(d string) structures.Timestamp { 21 | now := time.Now().UnixNano() 22 | 23 | dur,err := time.ParseDuration(d) 24 | 25 | if err!=nil { 26 | xdur,_ := time.ParseDuration("1h") 27 | //return structures.Timestamp(fmt.Sprintf("%d",now-xdur.Nanoseconds())) 28 | return structures.Timestamp(now-xdur.Nanoseconds()) 29 | 30 | } else { 31 | return structures.Timestamp(now-dur.Nanoseconds()) 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /scripts/att.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ELEMENT=765e0188-a609-49c0-bf61-3825849413cd 4 | POLICY=ba64f197-0eb3-4f3f-a74d-a9a8e0a3f17d 5 | 6 | EN="$(curl -s -X GET http://127.0.0.1:8520/element/$ELEMENT | jq -r .name)" 7 | PN="$(curl -s -X GET http://127.0.0.1:8520/policy/$POLICY | jq -r .name)" 8 | 9 | 10 | echo Applying $PN to $EN 11 | 12 | 13 | #open session 14 | SESSION="$(curl -s -X POST http://127.0.0.1:8520/session -H "Content-Type: application/json" --data '{"message":"test from curl"}' | jq -r .itemid)" 15 | 16 | #attest element 17 | CLAIMID="$(curl -s -X POST http://127.0.0.1:8520/attest -H "Content-Type: application/json" --data '{"eid":"'$ELEMENT'","pid":"'$POLICY'","sid":"'$SESSION'"}' | jq -r .itemid)" 18 | 19 | #close session 20 | curl -s -X DELETE http://127.0.0.1:8520/session/$SESSION > /dev/null 21 | 22 | #Print stuff 23 | echo Session was $SESSION with claim $CLAIMID 24 | curl -s -X GET http://127.0.0.1:8520/claim/$CLAIMID | jq .body.sha256 -------------------------------------------------------------------------------- /scripts/attAutomation/CreateElements.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Bash script that adds all the elements specified in the elements.txt file 4 | #to the attestation server. An element and expected values are created. 5 | #Policy 1 and policy 2 variables represent the policies and rule 1, rule 2 the 6 | #rules by which the expected values are created. 7 | 8 | server="194.157.71.11:8520" 9 | policy1="Pi Fakeboot CRTM" 10 | policy2="Pi Fakeboot SRTM" 11 | rule1="tpm2_attestedValue" 12 | rule2="tpm2_firmware" 13 | params='{"Test":"test2"}' 14 | 15 | session=$(./createSession.py $server -m "bash script test") 16 | echo $session 17 | 18 | while read -r name device; do 19 | ./createElement.py $device -d "$name element" -n $name -t "letstrust" -sE $server 20 | claim1=$(./attest.py -e $name -p "$policy1" -s $session -sE $server) 21 | claim2=$(./attest.py -e $name -p "$policy2" -s $session -sE $server) 22 | ./createExpected.py -n "expected value for $name" -d "expected value for policy $policy1" -e "$name" -p "$policy1" -s $session -c $claim1 -sE $server 23 | ./createExpected.py -n "expected value for $name" -d "expected value for policy $policy2" -e "$name" -p "$policy2" -s $session -c $claim2 -sE $server 24 | done < elements.txt 25 | 26 | 27 | ./closeSession.py $server -s $session 28 | -------------------------------------------------------------------------------- /scripts/attAutomation/GenerateKeys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Bash script that creates tpm keys on all devices specified in the elements.txt file 4 | 5 | while read -r name device; do 6 | ./createKeys.py $device 7 | done < elements.txt 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /scripts/attAutomation/README.txt: -------------------------------------------------------------------------------- 1 | Make sure to change the permissions for files, GenerateKeys.sh, CreateElements.sh and VerifyElements.sh 2 | Do this with command 'sudo chmod u+x '. 3 | 4 | Start by adding all elements that you wish to add to the attestation server 5 | to file elements.txt. The format for each device is the following; @ 6 | IMPORTANT: Make sure that the device name has no spaces. Leave one empty line at the end of the file. 7 | 8 | To create tpm keys on each of the devices run the GenerateKeys.sh script 9 | Note that you may be prompted to add the password for each device. 10 | This will only happen once since the ssh keys are saved. 11 | 12 | To create elements on the attestation server run the bash script CreateElements.sh. 13 | It will add the elements in elements.txt to the attestation server and create expected values 14 | according to the policies specified in the bash script. 15 | 16 | To verify devices that already exist on the attestation server, run the VerifyElements.sh 17 | bash script. It will verify all devices specified in the elements.txt file, according to 18 | the rules and policies specified in the bash script. 19 | 20 | -------------------------------------------------------------------------------- /scripts/attAutomation/VerifyElements.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Bash script to attest and verify all elements in the elements.txt file according to rules/ 4 | #and policies given by the policy1, policy2, rule1 and rule2 variables. 5 | #The server variable gives the address of the attestation server 6 | #given as the ip address and port number. 7 | 8 | server="194.157.71.11:8520" 9 | policy1="Pi Fakeboot CRTM" 10 | policy2="Pi Fakeboot SRTM" 11 | rule1="tpm2_attestedValue" 12 | rule2="tpm2_firmware" 13 | 14 | session=$(./createSession.py $server -m "bash script test") 15 | 16 | while read -r name device; do 17 | claim1=$(./attest.py -e $name -p "$policy1" -s $session -sE $server) 18 | claim2=$(./attest.py -e $name -p "$policy2" -s $session -sE $server) 19 | r1=$(./verify.py -r "$rule1" -s $session -c $claim1 -sE $server) 20 | r2=$(./verify.py -r "$rule2" -s $session -c $claim1 -sE $server) 21 | r3=$(./verify.py -r "$rule1" -s $session -c $claim2 -sE $server) 22 | r4=$(./verify.py -r "$rule2" -s $session -c $claim2 -sE $server) 23 | if [ $r1 -eq 0 ] && [ $r2 -eq 0 ] && [ $r3 -eq 0 ] && [ $r4 -eq 0 ] 24 | then 25 | echo "$name device is trusted" 26 | else 27 | echo "$name device is not trusted" 28 | fi 29 | 30 | done < elements.txt 31 | 32 | ./closeSession.py $server -s $session 33 | 34 | 35 | -------------------------------------------------------------------------------- /scripts/attAutomation/attest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import ga10pythonlib as ga10 3 | import argparse 4 | 5 | 6 | attestPars = argparse.ArgumentParser() 7 | #add name of the device 8 | attestPars.add_argument("-e", "--element", type=str, 9 | help="element name") 10 | attestPars.add_argument("-params", "--parameters", type= str, help="parameters name") 11 | 12 | #add description, this is optional, if this is not added the description will be generated automatically 13 | attestPars.add_argument("-p", "--policy", type= str, help="policy name") 14 | 15 | #tags such as tpm type, currently only supports one argument which is the tpm type 16 | attestPars.add_argument("-s", "--session", type = str, help="session id") 17 | 18 | attestPars.add_argument("-sE", "--server", type = str, help= "attestation server; :") 19 | attestArguments = attestPars.parse_args() 20 | 21 | 22 | 23 | ga10.attest(attestArguments.policy,attestArguments.server,attestArguments.element,attestArguments.session,attestArguments.parameters) 24 | -------------------------------------------------------------------------------- /scripts/attAutomation/closeSession.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import ga10pythonlib as ga10 3 | import argparse 4 | closeSessionPars = argparse.ArgumentParser() 5 | 6 | #add ip address, this is mandatory 7 | closeSessionPars.add_argument("ip", help= ":") 8 | 9 | closeSessionPars.add_argument("-s","--session", type=str, help = "session id") 10 | 11 | closeSessionArguments = closeSessionPars.parse_args() 12 | 13 | 14 | ga10.closeSession(closeSessionArguments.ip,closeSessionArguments.session) 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/attAutomation/createElement.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import ga10pythonlib as ga10 3 | import argparse 4 | 5 | #creates an element 6 | #argparse for create element function 7 | elementPars = argparse.ArgumentParser() 8 | #add name of the device 9 | elementPars.add_argument("-n", "--name", type=str, 10 | help="element name") 11 | 12 | #add description, this is optional, if this is not added the description will be generated automatically 13 | elementPars.add_argument("-d", "--description", type= str, help="description of element") 14 | 15 | #add ip address, this is mandatory 16 | elementPars.add_argument("device", help= "@") 17 | 18 | #tags such as tpm type, currently only supports one argument which is the tpm type 19 | elementPars.add_argument("-t", "--tag", type = str, help="tag") 20 | 21 | elementPars.add_argument("-sE", "--server", type=str, help= "attestation server; :") 22 | elementArguments = elementPars.parse_args() 23 | 24 | 25 | ga10.createElement(elementArguments.name,elementArguments.description,elementArguments.device,elementArguments.tag,elementArguments.server) -------------------------------------------------------------------------------- /scripts/attAutomation/createExpected.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import ga10pythonlib as ga10 3 | import argparse 4 | 5 | #arparse for create expected value function 6 | 7 | expectedPars = argparse.ArgumentParser() 8 | 9 | expectedPars.add_argument("-n", "--name", type = str, help = "expected value name") 10 | 11 | expectedPars.add_argument("-d", "--description", type = str, help = "description of expected value") 12 | 13 | expectedPars.add_argument("-e", "--element", type = str, help = "element used for expected value") 14 | 15 | expectedPars.add_argument("-p", "--policy", type = str, help = "policy used for expected value") 16 | 17 | expectedPars.add_argument("-c", "--claim", type = str, help = "claim id") 18 | 19 | expectedPars.add_argument("-s", "--session", type = str, help = "session id") 20 | 21 | expectedPars.add_argument("-sE", "--server", type = str, help= "attestation server; :") 22 | expectedArguments = expectedPars.parse_args() 23 | 24 | 25 | ga10.createExpected(expectedArguments.name,expectedArguments.description,expectedArguments.element,expectedArguments.policy,expectedArguments.session,expectedArguments.claim,expectedArguments.server) -------------------------------------------------------------------------------- /scripts/attAutomation/createKeys.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import argparse 3 | import ga10pythonlib as ga10 4 | #arparse for creating keys 5 | 6 | keyPars = argparse.ArgumentParser() 7 | 8 | keyPars.add_argument("device", help = "@") 9 | 10 | keyArguments = keyPars.parse_args() 11 | 12 | 13 | 14 | ga10.createKeys(keyArguments.device) -------------------------------------------------------------------------------- /scripts/attAutomation/createSession.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import ga10pythonlib as ga10 3 | import argparse 4 | #arparse for create session function 5 | 6 | sessionPars = argparse.ArgumentParser() 7 | 8 | #add ip address, this is mandatory 9 | sessionPars.add_argument("ip", help= ":") 10 | 11 | sessionPars.add_argument("-m", "--message", type = str, help = "message displayed with session creation") 12 | 13 | 14 | sessionArguments = sessionPars.parse_args() 15 | 16 | 17 | ga10.createSession(sessionArguments.ip,sessionArguments.message) -------------------------------------------------------------------------------- /scripts/attAutomation/elements.txt: -------------------------------------------------------------------------------- 1 | a lab@192.168.0.234 2 | b lab@192.168.0.204 3 | c lab@192.168.0.247 4 | -------------------------------------------------------------------------------- /scripts/attAutomation/verify.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import ga10pythonlib as ga10 3 | import argparse 4 | 5 | 6 | #argparse for create verify function 7 | verifyPars = argparse.ArgumentParser() 8 | 9 | 10 | verifyPars.add_argument("-r", "--rule", type = str, help="rule name") 11 | 12 | verifyPars.add_argument("-s", "--session", type = str, help="session id") 13 | 14 | verifyPars.add_argument("-c", "--claim", type = str, help = "claim id") 15 | 16 | verifyPars.add_argument("-sE", "--server", type = str, help= "attestation server; :") 17 | 18 | verifyArguments = verifyPars.parse_args() 19 | 20 | 21 | results = ga10.verify(verifyArguments.rule,verifyArguments.session,verifyArguments.claim,verifyArguments.server) 22 | 23 | print(results['result']) 24 | -------------------------------------------------------------------------------- /ta10/common/identifiers.go: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | import( 4 | "github.com/google/uuid" 5 | ) 6 | 7 | 8 | func MakeID() string { 9 | return uuid.New().String() 10 | } 11 | -------------------------------------------------------------------------------- /ta10/common/unsafemode.go: -------------------------------------------------------------------------------- 1 | package utilities 2 | 3 | 4 | var unsafemode bool = false 5 | 6 | func SetUnsafeMode() { 7 | unsafemode = true 8 | } 9 | 10 | func IsUnsafe() bool { 11 | return unsafemode 12 | } -------------------------------------------------------------------------------- /ta10/go.mod: -------------------------------------------------------------------------------- 1 | module ta10 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/google/go-tpm v0.9.0 7 | github.com/google/uuid v1.5.0 8 | github.com/labstack/echo/v4 v4.11.4 9 | ) 10 | 11 | require ( 12 | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect 13 | github.com/labstack/gommon v0.4.2 // indirect 14 | github.com/mattn/go-colorable v0.1.13 // indirect 15 | github.com/mattn/go-isatty v0.0.20 // indirect 16 | github.com/valyala/bytebufferpool v1.0.0 // indirect 17 | github.com/valyala/fasttemplate v1.2.2 // indirect 18 | golang.org/x/crypto v0.18.0 // indirect 19 | golang.org/x/net v0.20.0 // indirect 20 | golang.org/x/sys v0.16.0 // indirect 21 | golang.org/x/text v0.14.0 // indirect 22 | golang.org/x/time v0.5.0 // indirect 23 | 24 | ) 25 | -------------------------------------------------------------------------------- /ta10/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= 3 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 4 | github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= 5 | github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= 6 | github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= 7 | github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 8 | github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= 9 | github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= 10 | github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= 11 | github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= 12 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 13 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 14 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 15 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 16 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 17 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 18 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 19 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 20 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 21 | github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= 22 | github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 23 | golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= 24 | golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= 25 | golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= 26 | golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= 27 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 28 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 29 | golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= 30 | golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 31 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 32 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 33 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= 34 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 35 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 36 | -------------------------------------------------------------------------------- /ta10/ima/endpoints.go: -------------------------------------------------------------------------------- 1 | package ima 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | utilities "ta10/common" 9 | 10 | "github.com/labstack/echo/v4" 11 | ) 12 | 13 | const IMALOGLOCATION string = "/sys/kernel/security/ima/ascii_runtime_measurements" 14 | 15 | type returnASCIILog struct { 16 | ASCIILog string `json:"asciilog"` 17 | Encoding string `json:"encoded"` 18 | UnEncodedLength int `json:"unencodedlength"` 19 | EncodedLength int `json:"encodedlength"` 20 | } 21 | 22 | func GetEventLogLocation(loc string) string { 23 | fmt.Printf("IMA Log requested from %v, unsafe mode is %v, giving: ", loc, utilities.IsUnsafe()) 24 | 25 | if utilities.IsUnsafe() == true { 26 | fmt.Printf("%v\n", loc) 27 | return loc 28 | } else { 29 | fmt.Printf("%v\n", IMALOGLOCATION) 30 | return IMALOGLOCATION 31 | } 32 | } 33 | 34 | func ASCIILog(c echo.Context) error { 35 | fmt.Println("ima ascii called") 36 | 37 | var postbody map[string]interface{} 38 | var rtnbody = make(map[string]interface{}) 39 | 40 | if err := c.Bind(&postbody); err != nil { 41 | rtnbody["postbody"] = err.Error() 42 | return c.JSON(http.StatusBadRequest, rtnbody) 43 | } 44 | 45 | u := GetEventLogLocation(fmt.Sprintf("%v", postbody["ima/ASCIIlog"])) 46 | 47 | fcontent, err := ioutil.ReadFile(u) 48 | if err != nil { 49 | rtnbody["file err"] = err.Error() 50 | return c.JSON(http.StatusInternalServerError, rtnbody) 51 | } 52 | scontent := base64.StdEncoding.EncodeToString(fcontent) 53 | 54 | rtn := returnASCIILog{scontent, "base64", len(fcontent), len(scontent)} 55 | return c.JSON(http.StatusOK, rtn) 56 | } 57 | -------------------------------------------------------------------------------- /ta10/sys/endpoints.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import( 4 | "net/http" 5 | "runtime" 6 | "os" 7 | "fmt" 8 | 9 | "ta10/common" 10 | 11 | "github.com/labstack/echo/v4" 12 | ) 13 | 14 | type sysinfoReturn struct { 15 | OS string `json:"os"` 16 | Arch string `json:"arch"` 17 | NCPU int `json:"ncpu"` 18 | Hostname string `json:"hostname"` 19 | Unsafe bool `json:"unsafe"` 20 | Pid int `json:"pid"` 21 | Ppid int `json:"ppid"` 22 | 23 | 24 | } 25 | 26 | func getHostname() string { 27 | hostname := "?" 28 | 29 | h,err := os.Hostname() 30 | if (err==nil) { 31 | hostname=h 32 | } 33 | 34 | return hostname 35 | } 36 | 37 | 38 | func Sysinfo(c echo.Context) error { 39 | fmt.Println("sysinfo called") 40 | 41 | ncpus := runtime.NumCPU() 42 | 43 | 44 | s := sysinfoReturn{ runtime.GOOS, runtime.GOARCH, ncpus, getHostname(), utilities.IsUnsafe(), os.Getpid(), os.Getppid() } 45 | 46 | return c.JSON(http.StatusOK, s) 47 | } 48 | -------------------------------------------------------------------------------- /ta10/tpm2/opentpm_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package tpm2 4 | 5 | import( 6 | "fmt" 7 | "io" 8 | "net" 9 | "slices" 10 | 11 | "github.com/google/go-tpm/legacy/tpm2" 12 | ) 13 | 14 | var TPMDEVICES = []string{ "/dev/tpm0", "/dev/tpmrm0", "/dev/tpm1", "/dev/tpmrm1", } 15 | 16 | func OpenTPM(path string) (io.ReadWriteCloser,error) { 17 | fmt.Printf("TPM Device path >>> %v <<< passed as parameter. This is a Unix build: ",path) 18 | 19 | // Check if the path is a known device, else treat it as a unix domain socket 20 | if slices.Contains(TPMDEVICES,path) { 21 | fmt.Printf("Treating it as a device\n") 22 | return tpm2.OpenTPM(path) 23 | } else { 24 | fmt.Printf("Treating it as a TCP Unix domain socket\n") 25 | return net.Dial("tcp",path) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ta10/tpm2/opentpm_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package tpm2 4 | 5 | import( 6 | "fmt" 7 | "io" 8 | "github.com/google/go-tpm/legacy/tpm2" 9 | ) 10 | 11 | 12 | func OpenTPM(path string) (io.ReadWriteCloser,error) { 13 | fmt.Sprintf("TPM Device path >>> %v <<< passed as parameter. This is a Windows build and will be ignored.") 14 | rwc,err :=tpm2.OpenTPM() 15 | 16 | return rwc,err 17 | } 18 | -------------------------------------------------------------------------------- /ta10/uefi/endpoints.go: -------------------------------------------------------------------------------- 1 | package uefi 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | utilities "ta10/common" 10 | 11 | "github.com/labstack/echo/v4" 12 | ) 13 | 14 | const UEFIEVENTLOGLOCATION string = "/sys/kernel/security/tpm0/binary_bios_measurements" 15 | 16 | type returnEventLog struct { 17 | EventLog string `json:"eventlog"` 18 | Encoding string `json:"encoded"` 19 | UnEncodedLength int `json:"unencodedlength"` 20 | EncodedLength int `json:"encodedlength"` 21 | } 22 | 23 | func GetEventLogLocation(loc string) string { 24 | fmt.Printf("UEFI Log requested from %v, unsafe mode is %v, giving: ", loc, utilities.IsUnsafe()) 25 | 26 | if utilities.IsUnsafe() == true { 27 | fmt.Printf("%v\n", loc) 28 | return loc 29 | } else { 30 | fmt.Printf("%v\n", UEFIEVENTLOGLOCATION) 31 | return UEFIEVENTLOGLOCATION 32 | } 33 | } 34 | 35 | func Eventlog(c echo.Context) error { 36 | fmt.Println("eventlog called") 37 | 38 | var postbody map[string]interface{} 39 | var rtnbody = make(map[string]interface{}) 40 | 41 | if err := c.Bind(&postbody); err != nil { 42 | rtnbody["postbody"] = err.Error() 43 | return c.JSON(http.StatusUnprocessableEntity, rtnbody) 44 | } 45 | 46 | u := GetEventLogLocation(fmt.Sprintf("%v", postbody["uefi/eventlog"])) 47 | 48 | fcontent, err := ioutil.ReadFile(u) 49 | if err != nil { 50 | rtnbody["file err"] = err.Error() 51 | return c.JSON(http.StatusInternalServerError, rtnbody) 52 | } 53 | scontent := base64.StdEncoding.EncodeToString(fcontent) 54 | 55 | rtn := returnEventLog{scontent, "base64", len(fcontent), len(scontent)} 56 | return c.JSON(http.StatusOK, rtn) 57 | } 58 | --------------------------------------------------------------------------------