Repository: pq-code-package/mldsa-native
Pull request #178: CI: Add EC2 runners and move CBMC there
Author: login: mkannwischer
Created: 2025-04-22T08:36:27Z | Merged: 2025-04-28T03:51:46Z



Diff:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 29c6cc1b8..1ca52721b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -274,34 +274,76 @@ jobs:
           cflags: "-std=c23"
   cbmc_44:
     name: CBMC (ML-DSA-44)
+    if: ${{ github.repository_owner == 'pq-code-package' && !github.event.pull_request.head.repo.fork }}
     needs: [quickcheck, quickcheck_bench, quickcheck-c90, lint]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: ./.github/actions/cbmc
-        with:
-          mldsa_mode: 2
-          gh_token: ${{ secrets.GITHUB_TOKEN }}
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    uses: ./.github/workflows/ci_ec2_reusable.yml
+    with:
+      name: CBMC (ML-DSA-44)
+      ec2_instance_type: c7g.4xlarge
+      ec2_ami: ubuntu-latest (custom AMI)
+      ec2_ami_id: ami-0d7f502261b31b27f # aarch64, ubuntu-latest, 64g
+      compile_mode: native
+      opt: no_opt
+      lint: false
+      verbose: true
+      functest: true
+      kattest: false
+      nistkattest: false
+      acvptest: false
+      cbmc: true
+      cbmc_mldsa_mode: 2
+    secrets: inherit
   cbmc_65:
     name: CBMC (ML-DSA-65)
+    if: ${{ github.repository_owner == 'pq-code-package' && !github.event.pull_request.head.repo.fork }}
     needs: [quickcheck, quickcheck_bench, quickcheck-c90, lint]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: ./.github/actions/cbmc
-        with:
-          mldsa_mode: 3
-          gh_token: ${{ secrets.GITHUB_TOKEN }}
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    uses: ./.github/workflows/ci_ec2_reusable.yml
+    with:
+      name: CBMC (ML-DSA-65)
+      ec2_instance_type: c7g.4xlarge
+      ec2_ami: ubuntu-latest (custom AMI)
+      ec2_ami_id: ami-0d7f502261b31b27f # aarch64, ubuntu-latest, 64g
+      compile_mode: native
+      opt: no_opt
+      lint: false
+      verbose: true
+      functest: true
+      kattest: false
+      nistkattest: false
+      acvptest: false
+      cbmc: true
+      cbmc_mldsa_mode: 2
+    secrets: inherit
   cbmc_87:
     name: CBMC (ML-DSA-87)
+    if: ${{ github.repository_owner == 'pq-code-package' && !github.event.pull_request.head.repo.fork }}
     needs: [quickcheck, quickcheck_bench, quickcheck-c90, lint]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: ./.github/actions/cbmc
-        with:
-          mldsa_mode: 5
-          gh_token: ${{ secrets.GITHUB_TOKEN }}
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    uses: ./.github/workflows/ci_ec2_reusable.yml
+    with:
+      name: CBMC (ML-DSA-87)
+      ec2_instance_type: c7g.4xlarge
+      ec2_ami: ubuntu-latest (custom AMI)
+      ec2_ami_id: ami-0d7f502261b31b27f # aarch64, ubuntu-latest, 64g
+      compile_mode: native
+      opt: no_opt
+      lint: false
+      verbose: true
+      functest: true
+      kattest: false
+      nistkattest: false
+      acvptest: false
+      cbmc: true
+      cbmc_mldsa_mode: 5
+    secrets: inherit
   check_autogenerated_files:
     strategy:
       fail-fast: false
diff --git a/.github/workflows/ci_ec2_reusable.yml b/.github/workflows/ci_ec2_reusable.yml
new file mode 100644
index 000000000..cc7b0b08b
--- /dev/null
+++ b/.github/workflows/ci_ec2_reusable.yml
@@ -0,0 +1,213 @@
+# SPDX-License-Identifier: Apache-2.0
+
+name: ci-ec2-reusable
+permissions:
+  contents: read
+on:
+  workflow_call:
+    inputs:
+      name:
+        type: string
+        description: Alternative name of instance
+        default: Graviton2
+      ec2_instance_type:
+        type: string
+        description: Type if EC2 instance to benchmark on
+        default: t4g.small
+      ec2_ami:
+        type: string
+        description: Textual description of AMI
+        default: ubuntu-latest (aarch64)
+      ec2_ami_id:
+        type: string
+        description: AMI ID
+        default: ami-0e8c824f386e1de06
+      cflags:
+        type: string
+        description: Custom CFLAGS for compilation
+        default: ""
+      verbose:
+        description: Determine for the log verbosity
+        type: boolean
+        default: false
+      compile_mode:
+        type: string
+        description: either all, native, cross or none
+        default: all
+      opt:
+        type: string
+        description: either all, opt or no_opt
+        default: all
+      functest:
+        type: boolean
+        default: true
+      kattest:
+        type: boolean
+        default: true
+      nistkattest:
+        type: boolean
+        default: true
+      acvptest:
+        type: boolean
+        default: true
+      lint:
+        type: boolean
+        default: true
+      test:
+        type: boolean
+        default: true
+      cbmc:
+        type: boolean
+        default: false
+      slothy:
+        type: boolean
+        default: false
+      cbmc_mldsa_mode:
+        type: string
+        default: 2
+env:
+  AWS_ROLE: arn:aws:iam::904233116199:role/mldsa-native-ci
+  AWS_REGION: us-east-1
+  AMI_UBUNTU_LATEST_X86_64: ami-0e86e20dae9224db8
+  AMI_UBUNTU_LATEST_AARCH64: ami-096ea6a12ea24a797
+jobs:
+  start-ec2-runner:
+    name: Start instance (${{ inputs.ec2_instance_type }})
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    runs-on: ubuntu-latest
+    if: ${{ always() }} # The point is to make this step non-cancellable,
+                        # avoiding race conditions where an instance is started,
+                        # but isn't yet done registering as a runner and reporting back.
+    outputs:
+      label: ${{ steps.remember-runner.outputs.label }}
+      ec2-instance-id: ${{ steps.remember-runner.outputs.ec2-instance-id }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Determine AMI ID
+        id: det_ami_id
+        run: |
+          if [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (x86_64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_X86_64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (aarch64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_AARCH64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (custom AMI)" ]]; then
+            AMI_ID=${{ inputs.ec2_ami_id }}
+          fi
+          echo "Using AMI ID: $AMI_ID"
+          echo "AMI_ID=$AMI_ID" >> $GITHUB_OUTPUT
+      - name: Configure AWS credentials
+        uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
+        with:
+          role-to-assume: ${{ env.AWS_ROLE }}
+          aws-region: ${{ env.AWS_REGION }}
+      - name: Start EC2 runner
+        id: start-ec2-runner-first
+        continue-on-error: true
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Start EC2c runner (wait before retry)
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        shell: bash
+        run: |
+          sleep 30 # Wait 30s before retrying
+          sleep $((1 + RANDOM % 30))
+      - name: Start EC2 runner (retry)
+        id: start-ec2-runner-second
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Remember runner
+        id: remember-runner
+        shell: bash
+        run: |
+          if [[ "${{ steps.start-ec2-runner-first.outcome }}" == "failure" ]]; then
+            echo "label=${{ steps.start-ec2-runner-second.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-second.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          else
+            echo "label=${{ steps.start-ec2-runner-first.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-first.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          fi
+
+  tests:
+    name: Run tests
+    needs: start-ec2-runner
+    runs-on: ${{ needs.start-ec2-runner.outputs.label }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Linting
+        if: ${{ inputs.lint }}
+        uses: ./.github/actions/lint
+        with:
+          nix-shell: ci-linter
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          nix-verbose: ${{ inputs.verbose }}
+      - name: Functional Tests
+        if: ${{ inputs.test }}
+        uses: ./.github/actions/multi-functest
+        with:
+          nix-shell: ${{ (inputs.compile_mode == 'cross' || inputs.compile_mode == 'all') && 'ci-cross' || 'ci' }}
+          nix-cache: ${{ inputs.cbmc || inputs.compile_mode == 'cross' || inputs.compile_mode == 'all' }}
+          nix-verbose: ${{ inputs.verbose }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          cflags: ${{ inputs.cflags }}
+          compile_mode: ${{ inputs.compile_mode }}
+          opt: ${{ inputs.opt }}
+          func: ${{ inputs.functest }}
+          kat: ${{ inputs.kattest }}
+          nistkat: ${{ inputs.nistkattest }}
+          acvp: ${{ inputs.acvptest }}
+      - name: CBMC
+        if: ${{ inputs.cbmc && (success() || failure()) }}
+        uses: ./.github/actions/cbmc
+        with:
+          nix-shell: ci-cbmc
+          nix-verbose: ${{ inputs.verbose }}
+          mldsa_mode: ${{ inputs.cbmc_mldsa_mode }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+      # - name: SLOTHY
+      #   if: ${{ inputs.slothy }}
+      #   uses: ./.github/actions/setup-shell
+      #   with:
+      #     gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+      #     nix-cache: true
+      #     nix-shell: ci-slothy
+      #     script: |
+      #       autogen --slothy
+      #       tests all --opt opt
+  stop-ec2-runner:
+    name: Stop instance (${{ inputs.ec2_instance_type }})
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    needs:
+      - start-ec2-runner
+      - tests
+    runs-on: ubuntu-latest
+    if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
+    steps:
+      - name: Configure AWS credentials
+        uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
+        with:
+          role-to-assume: ${{ env.AWS_ROLE }}
+          aws-region: ${{ env.AWS_REGION }}
+      - name: Stop EC2 runner
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: stop
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          label: ${{ needs.start-ec2-runner.outputs.label }}
+          ec2-instance-id: ${{ needs.start-ec2-runner.outputs.ec2-instance-id }}


Reviews:
user: login: hanno-becker
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:20:55Z
user: login: mkannwischer
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T01:18:32Z
user: login: hanno-becker
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T03:20:43Z
user: login: hanno-becker
body: LGTM apart from a stray section on SLOTHY, which should be removed
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T03:27:20Z
user: login: mkannwischer
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T03:40:34Z
user: login: hanno-becker
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T03:48:21Z
user: login: hanno-becker
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T03:48:35Z

Review comments:
diff_hunk: @@ -274,34 +274,76 @@ jobs:
           cflags: "-std=c23"
   cbmc_44:
     name: CBMC (ML-DSA-44)
+    if: ${{ github.repository_owner == 'pq-code-package' && !github.event.pull_request.head.repo.fork }}
     needs: [quickcheck, quickcheck_bench, quickcheck-c90, lint]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: ./.github/actions/cbmc
-        with:
-          mldsa_mode: 2
-          gh_token: ${{ secrets.GITHUB_TOKEN }}
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    uses: ./.github/workflows/ci_ec2_reusable.yml
+    with:
+      name: CBMC (MLKEM-512)
+      ec2_instance_type: c7g.4xlarge
+      ec2_ami: ubuntu-latest (custom AMI)
+      ec2_ami_id: ami-0d7f502261b31b27f # aarch64, ubuntu-latest, 64g
+      compile_mode: native
+      opt: no_opt
+      lint: false
+      verbose: true
+      functest: true
+      kattest: false
+      nistkattest: false
+      acvptest: false
+      cbmc: true
+      cbmc_mldsa_mode: 2
+    secrets: inherit
   cbmc_65:
     name: CBMC (ML-DSA-65)
+    if: ${{ github.repository_owner == 'pq-code-package' && !github.event.pull_request.head.repo.fork }}
     needs: [quickcheck, quickcheck_bench, quickcheck-c90, lint]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: ./.github/actions/cbmc
-        with:
-          mldsa_mode: 3
-          gh_token: ${{ secrets.GITHUB_TOKEN }}
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    uses: ./.github/workflows/ci_ec2_reusable.yml
+    with:
+      name: CBMC (MLKEM-512)
path: .github/workflows/ci.yml
user: login: hanno-becker
body: Copy pasta
created_at: 2025-04-25T09:20:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -274,34 +274,76 @@ jobs:
           cflags: "-std=c23"
   cbmc_44:
     name: CBMC (ML-DSA-44)
+    if: ${{ github.repository_owner == 'pq-code-package' && !github.event.pull_request.head.repo.fork }}
     needs: [quickcheck, quickcheck_bench, quickcheck-c90, lint]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: ./.github/actions/cbmc
-        with:
-          mldsa_mode: 2
-          gh_token: ${{ secrets.GITHUB_TOKEN }}
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    uses: ./.github/workflows/ci_ec2_reusable.yml
+    with:
+      name: CBMC (MLKEM-512)
+      ec2_instance_type: c7g.4xlarge
+      ec2_ami: ubuntu-latest (custom AMI)
+      ec2_ami_id: ami-0d7f502261b31b27f # aarch64, ubuntu-latest, 64g
+      compile_mode: native
+      opt: no_opt
+      lint: false
+      verbose: true
+      functest: true
+      kattest: false
+      nistkattest: false
+      acvptest: false
+      cbmc: true
+      cbmc_mldsa_mode: 2
+    secrets: inherit
   cbmc_65:
     name: CBMC (ML-DSA-65)
+    if: ${{ github.repository_owner == 'pq-code-package' && !github.event.pull_request.head.repo.fork }}
     needs: [quickcheck, quickcheck_bench, quickcheck-c90, lint]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-      - uses: ./.github/actions/cbmc
-        with:
-          mldsa_mode: 3
-          gh_token: ${{ secrets.GITHUB_TOKEN }}
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    uses: ./.github/workflows/ci_ec2_reusable.yml
+    with:
+      name: CBMC (MLKEM-512)
path: .github/workflows/ci.yml
user: login: mkannwischer
body: Fixed.
created_at: 2025-04-28T01:18:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,213 @@
+# SPDX-License-Identifier: Apache-2.0
+
+name: ci-ec2-reusable
+permissions:
+  contents: read
+on:
+  workflow_call:
+    inputs:
+      name:
+        type: string
+        description: Alternative name of instance
+        default: Graviton2
+      ec2_instance_type:
+        type: string
+        description: Type if EC2 instance to benchmark on
+        default: t4g.small
+      ec2_ami:
+        type: string
+        description: Textual description of AMI
+        default: ubuntu-latest (aarch64)
+      ec2_ami_id:
+        type: string
+        description: AMI ID
+        default: ami-0e8c824f386e1de06
+      cflags:
+        type: string
+        description: Custom CFLAGS for compilation
+        default: ""
+      verbose:
+        description: Determine for the log verbosity
+        type: boolean
+        default: false
+      compile_mode:
+        type: string
+        description: either all, native, cross or none
+        default: all
+      opt:
+        type: string
+        description: either all, opt or no_opt
+        default: all
+      functest:
+        type: boolean
+        default: true
+      kattest:
+        type: boolean
+        default: true
+      nistkattest:
+        type: boolean
+        default: true
+      acvptest:
+        type: boolean
+        default: true
+      lint:
+        type: boolean
+        default: true
+      test:
+        type: boolean
+        default: true
+      cbmc:
+        type: boolean
+        default: false
+      slothy:
+        type: boolean
+        default: false
+      cbmc_mldsa_mode:
+        type: string
+        default: 2
+env:
+  AWS_ROLE: arn:aws:iam::904233116199:role/mldsa-native-ci
+  AWS_REGION: us-east-1
+  AMI_UBUNTU_LATEST_X86_64: ami-0e86e20dae9224db8
+  AMI_UBUNTU_LATEST_AARCH64: ami-096ea6a12ea24a797
+jobs:
+  start-ec2-runner:
+    name: Start instance (${{ inputs.ec2_instance_type }})
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    runs-on: ubuntu-latest
+    if: ${{ always() }} # The point is to make this step non-cancellable,
+                        # avoiding race conditions where an instance is started,
+                        # but isn't yet done registering as a runner and reporting back.
+    outputs:
+      label: ${{ steps.remember-runner.outputs.label }}
+      ec2-instance-id: ${{ steps.remember-runner.outputs.ec2-instance-id }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Determine AMI ID
+        id: det_ami_id
+        run: |
+          if [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (x86_64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_X86_64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (aarch64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_AARCH64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (custom AMI)" ]]; then
+            AMI_ID=${{ inputs.ec2_ami_id }}
+          fi
+          echo "Using AMI ID: $AMI_ID"
+          echo "AMI_ID=$AMI_ID" >> $GITHUB_OUTPUT
+      - name: Configure AWS credentials
+        uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
+        with:
+          role-to-assume: ${{ env.AWS_ROLE }}
+          aws-region: ${{ env.AWS_REGION }}
+      - name: Start EC2 runner
+        id: start-ec2-runner-first
+        continue-on-error: true
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Start EC2c runner (wait before retry)
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        shell: bash
+        run: |
+          sleep 30 # Wait 30s before retrying
+          sleep $((1 + RANDOM % 30))
+      - name: Start EC2 runner (retry)
+        id: start-ec2-runner-second
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Remember runner
+        id: remember-runner
+        shell: bash
+        run: |
+          if [[ "${{ steps.start-ec2-runner-first.outcome }}" == "failure" ]]; then
+            echo "label=${{ steps.start-ec2-runner-second.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-second.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          else
+            echo "label=${{ steps.start-ec2-runner-first.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-first.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          fi
+
+  tests:
+    name: Run tests
+    needs: start-ec2-runner
+    runs-on: ${{ needs.start-ec2-runner.outputs.label }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Linting
+        if: ${{ inputs.lint }}
+        uses: ./.github/actions/lint
+        with:
+          nix-shell: ci-linter
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          nix-verbose: ${{ inputs.verbose }}
+      - name: Functional Tests
+        if: ${{ inputs.test }}
+        uses: ./.github/actions/multi-functest
+        with:
+          nix-shell: ${{ (inputs.compile_mode == 'cross' || inputs.compile_mode == 'all') && 'ci-cross' || 'ci' }}
+          nix-cache: ${{ inputs.cbmc || inputs.compile_mode == 'cross' || inputs.compile_mode == 'all' }}
+          nix-verbose: ${{ inputs.verbose }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          cflags: ${{ inputs.cflags }}
+          compile_mode: ${{ inputs.compile_mode }}
+          opt: ${{ inputs.opt }}
+          func: ${{ inputs.functest }}
+          kat: ${{ inputs.kattest }}
+          nistkat: ${{ inputs.nistkattest }}
+          acvp: ${{ inputs.acvptest }}
+      - name: CBMC
+        if: ${{ inputs.cbmc && (success() || failure()) }}
+        uses: ./.github/actions/cbmc
+        with:
+          nix-shell: ci-cbmc
+          nix-verbose: ${{ inputs.verbose }}
+          mldsa_mode: ${{ inputs.cbmc_mldsa_mode }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+      - name: SLOTHY
path: .github/workflows/ci_ec2_reusable.yml
user: login: hanno-becker
body: Is this copy-pasta or does it do something? 
created_at: 2025-04-28T03:20:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,213 @@
+# SPDX-License-Identifier: Apache-2.0
+
+name: ci-ec2-reusable
+permissions:
+  contents: read
+on:
+  workflow_call:
+    inputs:
+      name:
+        type: string
+        description: Alternative name of instance
+        default: Graviton2
+      ec2_instance_type:
+        type: string
+        description: Type if EC2 instance to benchmark on
+        default: t4g.small
+      ec2_ami:
+        type: string
+        description: Textual description of AMI
+        default: ubuntu-latest (aarch64)
+      ec2_ami_id:
+        type: string
+        description: AMI ID
+        default: ami-0e8c824f386e1de06
+      cflags:
+        type: string
+        description: Custom CFLAGS for compilation
+        default: ""
+      verbose:
+        description: Determine for the log verbosity
+        type: boolean
+        default: false
+      compile_mode:
+        type: string
+        description: either all, native, cross or none
+        default: all
+      opt:
+        type: string
+        description: either all, opt or no_opt
+        default: all
+      functest:
+        type: boolean
+        default: true
+      kattest:
+        type: boolean
+        default: true
+      nistkattest:
+        type: boolean
+        default: true
+      acvptest:
+        type: boolean
+        default: true
+      lint:
+        type: boolean
+        default: true
+      test:
+        type: boolean
+        default: true
+      cbmc:
+        type: boolean
+        default: false
+      slothy:
+        type: boolean
+        default: false
+      cbmc_mldsa_mode:
+        type: string
+        default: 2
+env:
+  AWS_ROLE: arn:aws:iam::904233116199:role/mldsa-native-ci
+  AWS_REGION: us-east-1
+  AMI_UBUNTU_LATEST_X86_64: ami-0e86e20dae9224db8
+  AMI_UBUNTU_LATEST_AARCH64: ami-096ea6a12ea24a797
+jobs:
+  start-ec2-runner:
+    name: Start instance (${{ inputs.ec2_instance_type }})
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    runs-on: ubuntu-latest
+    if: ${{ always() }} # The point is to make this step non-cancellable,
+                        # avoiding race conditions where an instance is started,
+                        # but isn't yet done registering as a runner and reporting back.
+    outputs:
+      label: ${{ steps.remember-runner.outputs.label }}
+      ec2-instance-id: ${{ steps.remember-runner.outputs.ec2-instance-id }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Determine AMI ID
+        id: det_ami_id
+        run: |
+          if [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (x86_64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_X86_64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (aarch64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_AARCH64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (custom AMI)" ]]; then
+            AMI_ID=${{ inputs.ec2_ami_id }}
+          fi
+          echo "Using AMI ID: $AMI_ID"
+          echo "AMI_ID=$AMI_ID" >> $GITHUB_OUTPUT
+      - name: Configure AWS credentials
+        uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
+        with:
+          role-to-assume: ${{ env.AWS_ROLE }}
+          aws-region: ${{ env.AWS_REGION }}
+      - name: Start EC2 runner
+        id: start-ec2-runner-first
+        continue-on-error: true
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Start EC2c runner (wait before retry)
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        shell: bash
+        run: |
+          sleep 30 # Wait 30s before retrying
+          sleep $((1 + RANDOM % 30))
+      - name: Start EC2 runner (retry)
+        id: start-ec2-runner-second
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Remember runner
+        id: remember-runner
+        shell: bash
+        run: |
+          if [[ "${{ steps.start-ec2-runner-first.outcome }}" == "failure" ]]; then
+            echo "label=${{ steps.start-ec2-runner-second.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-second.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          else
+            echo "label=${{ steps.start-ec2-runner-first.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-first.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          fi
+
+  tests:
+    name: Run tests
+    needs: start-ec2-runner
+    runs-on: ${{ needs.start-ec2-runner.outputs.label }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Linting
+        if: ${{ inputs.lint }}
+        uses: ./.github/actions/lint
+        with:
+          nix-shell: ci-linter
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          nix-verbose: ${{ inputs.verbose }}
+      - name: Functional Tests
+        if: ${{ inputs.test }}
+        uses: ./.github/actions/multi-functest
+        with:
+          nix-shell: ${{ (inputs.compile_mode == 'cross' || inputs.compile_mode == 'all') && 'ci-cross' || 'ci' }}
+          nix-cache: ${{ inputs.cbmc || inputs.compile_mode == 'cross' || inputs.compile_mode == 'all' }}
+          nix-verbose: ${{ inputs.verbose }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          cflags: ${{ inputs.cflags }}
+          compile_mode: ${{ inputs.compile_mode }}
+          opt: ${{ inputs.opt }}
+          func: ${{ inputs.functest }}
+          kat: ${{ inputs.kattest }}
+          nistkat: ${{ inputs.nistkattest }}
+          acvp: ${{ inputs.acvptest }}
+      - name: CBMC
+        if: ${{ inputs.cbmc && (success() || failure()) }}
+        uses: ./.github/actions/cbmc
+        with:
+          nix-shell: ci-cbmc
+          nix-verbose: ${{ inputs.verbose }}
+          mldsa_mode: ${{ inputs.cbmc_mldsa_mode }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+      - name: SLOTHY
path: .github/workflows/ci_ec2_reusable.yml
user: login: mkannwischer
body: I commented it out, okay? Once we have SLOTHYed code, we should re-add it.
created_at: 2025-04-28T03:40:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,213 @@
+# SPDX-License-Identifier: Apache-2.0
+
+name: ci-ec2-reusable
+permissions:
+  contents: read
+on:
+  workflow_call:
+    inputs:
+      name:
+        type: string
+        description: Alternative name of instance
+        default: Graviton2
+      ec2_instance_type:
+        type: string
+        description: Type if EC2 instance to benchmark on
+        default: t4g.small
+      ec2_ami:
+        type: string
+        description: Textual description of AMI
+        default: ubuntu-latest (aarch64)
+      ec2_ami_id:
+        type: string
+        description: AMI ID
+        default: ami-0e8c824f386e1de06
+      cflags:
+        type: string
+        description: Custom CFLAGS for compilation
+        default: ""
+      verbose:
+        description: Determine for the log verbosity
+        type: boolean
+        default: false
+      compile_mode:
+        type: string
+        description: either all, native, cross or none
+        default: all
+      opt:
+        type: string
+        description: either all, opt or no_opt
+        default: all
+      functest:
+        type: boolean
+        default: true
+      kattest:
+        type: boolean
+        default: true
+      nistkattest:
+        type: boolean
+        default: true
+      acvptest:
+        type: boolean
+        default: true
+      lint:
+        type: boolean
+        default: true
+      test:
+        type: boolean
+        default: true
+      cbmc:
+        type: boolean
+        default: false
+      slothy:
+        type: boolean
+        default: false
+      cbmc_mldsa_mode:
+        type: string
+        default: 2
+env:
+  AWS_ROLE: arn:aws:iam::904233116199:role/mldsa-native-ci
+  AWS_REGION: us-east-1
+  AMI_UBUNTU_LATEST_X86_64: ami-0e86e20dae9224db8
+  AMI_UBUNTU_LATEST_AARCH64: ami-096ea6a12ea24a797
+jobs:
+  start-ec2-runner:
+    name: Start instance (${{ inputs.ec2_instance_type }})
+    permissions:
+      contents: 'read'
+      id-token: 'write'
+    runs-on: ubuntu-latest
+    if: ${{ always() }} # The point is to make this step non-cancellable,
+                        # avoiding race conditions where an instance is started,
+                        # but isn't yet done registering as a runner and reporting back.
+    outputs:
+      label: ${{ steps.remember-runner.outputs.label }}
+      ec2-instance-id: ${{ steps.remember-runner.outputs.ec2-instance-id }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Determine AMI ID
+        id: det_ami_id
+        run: |
+          if [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (x86_64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_X86_64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (aarch64)" ]]; then
+            AMI_ID=${{ env.AMI_UBUNTU_LATEST_AARCH64 }}
+          elif [[ "${{ inputs.ec2_ami }}" == "ubuntu-latest (custom AMI)" ]]; then
+            AMI_ID=${{ inputs.ec2_ami_id }}
+          fi
+          echo "Using AMI ID: $AMI_ID"
+          echo "AMI_ID=$AMI_ID" >> $GITHUB_OUTPUT
+      - name: Configure AWS credentials
+        uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
+        with:
+          role-to-assume: ${{ env.AWS_ROLE }}
+          aws-region: ${{ env.AWS_REGION }}
+      - name: Start EC2 runner
+        id: start-ec2-runner-first
+        continue-on-error: true
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Start EC2c runner (wait before retry)
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        shell: bash
+        run: |
+          sleep 30 # Wait 30s before retrying
+          sleep $((1 + RANDOM % 30))
+      - name: Start EC2 runner (retry)
+        id: start-ec2-runner-second
+        if: steps.start-ec2-runner-first.outcome == 'failure'
+        uses: machulav/ec2-github-runner@a8c20fc0876503410b2b966c124abc2311984ce2 # v2.3.9
+        with:
+          mode: start
+          github-token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          ec2-image-id: ${{ steps.det_ami_id.outputs.AMI_ID }}
+          ec2-instance-type: ${{ inputs.ec2_instance_type }}
+          subnet-id: subnet-094d73eb42eb6bf5b
+          security-group-id: sg-0282706dbc92a1579
+      - name: Remember runner
+        id: remember-runner
+        shell: bash
+        run: |
+          if [[ "${{ steps.start-ec2-runner-first.outcome }}" == "failure" ]]; then
+            echo "label=${{ steps.start-ec2-runner-second.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-second.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          else
+            echo "label=${{ steps.start-ec2-runner-first.outputs.label }}" >> "$GITHUB_OUTPUT"
+            echo "ec2-instance-id=${{ steps.start-ec2-runner-first.outputs.ec2-instance-id }}" >> "$GITHUB_OUTPUT"
+          fi
+
+  tests:
+    name: Run tests
+    needs: start-ec2-runner
+    runs-on: ${{ needs.start-ec2-runner.outputs.label }}
+    steps:
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+      - name: Linting
+        if: ${{ inputs.lint }}
+        uses: ./.github/actions/lint
+        with:
+          nix-shell: ci-linter
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          nix-verbose: ${{ inputs.verbose }}
+      - name: Functional Tests
+        if: ${{ inputs.test }}
+        uses: ./.github/actions/multi-functest
+        with:
+          nix-shell: ${{ (inputs.compile_mode == 'cross' || inputs.compile_mode == 'all') && 'ci-cross' || 'ci' }}
+          nix-cache: ${{ inputs.cbmc || inputs.compile_mode == 'cross' || inputs.compile_mode == 'all' }}
+          nix-verbose: ${{ inputs.verbose }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+          cflags: ${{ inputs.cflags }}
+          compile_mode: ${{ inputs.compile_mode }}
+          opt: ${{ inputs.opt }}
+          func: ${{ inputs.functest }}
+          kat: ${{ inputs.kattest }}
+          nistkat: ${{ inputs.nistkattest }}
+          acvp: ${{ inputs.acvptest }}
+      - name: CBMC
+        if: ${{ inputs.cbmc && (success() || failure()) }}
+        uses: ./.github/actions/cbmc
+        with:
+          nix-shell: ci-cbmc
+          nix-verbose: ${{ inputs.verbose }}
+          mldsa_mode: ${{ inputs.cbmc_mldsa_mode }}
+          gh_token: ${{ secrets.AWS_GITHUB_TOKEN }}
+      - name: SLOTHY
path: .github/workflows/ci_ec2_reusable.yml
user: login: hanno-becker
body: Ok
created_at: 2025-04-28T03:48:21Z
author_association: CONTRIBUTOR

PR comments:
user: login: mkannwischer
created_at: 2025-04-23T03:10:40Z
body: Moving CBMC to more beefy EC2 runners does not result in significantly faster proof time. No need to do that. Maybe we go straight to adding benchmarking.
author_association: CONTRIBUTOR
user: login: mkannwischer
created_at: 2025-04-25T08:11:54Z
body: > Moving CBMC to more beefy EC2 runners does not result in significantly faster proof time. No need to do that. Maybe we go straight to adding benchmarking.

I found out why it is not faster - this was actually recompiling CBMC in CI. This is because somehow the Arm64 CI cache entry got evicted. I'm rebuilding it now in https://github.com/pq-code-package/mldsa-native/actions/runs/14659779817/job/41141438281. Once that is done, we can rebase this PR and it should be quite a bit faster than on standard Github runners. It's also required to make the Keccak proofs in #181 work. 
author_association: CONTRIBUTOR
user: login: hanno-becker
created_at: 2025-04-28T03:27:43Z
body: @mkannwischer Should this still be marked `DO-NOT-MERGE`?
author_association: CONTRIBUTOR