arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 76

VxSuite TDP - v4

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

VxAdmin Results Exports

VxAdmin supports a variety of results exports.

Tally reports contain contest results for the full election or a specific subset of ballots. They can be printed directly from VxAdmin, exported as PDFs, or exported in CSV format. In addition, full election results can be exported as an Election Results Reporting CDF JSON file.

Ballot count reports include only ballot counts, without contest results. They can also be printed directly from VxAdmin, exported as PDFs, or exported in CSV format.

The write-in adjudication report acts as a summary of all write-in adjudication activity or as a "scatter report." The tally reports consolidates write-in candidates whose vote totals are too small to affect the contest outcomes. The counts for those write-in candidates are available in the write-in adjudication report. The write-in adjudication report may be printed directly from VxAdmin or exported as a PDF.

For all VxAdmin reports, the report is either "Official" or "Unofficial." If the report is exported before the results are marked as official in the application, the results are "Unofficial." If the report is exported after the results are marked as official in the application, the results are "Official." All visual reports have "Official" or "Unofficial" included in the title and all exported files will have "official" or "unofficial" included in the filename.

Machine Marked Ballots

After a voter is done making vote selections with VxMarkScan, the machine will print a ballot representing the selections. The voter reviews the ballot and verifies ballot selections. The ballot is then cast into the attached ballot box.

VxMarkScan Ballot

hashtag
Ballot Layout

Parts of a VxMarkScan Ballot

The ballot displays information about the election, metadata about the ballot, and the voter's selections. The selections are both displayed and encoded in the QR code.

Ballot Component
Details

The blank space at the top of the ballot is included so that all of the ballot content is visible when VxMarkScan presents the ballot for the voter to review (since the top part of the ballot is held in the machine).

hashtag
Multi-Lingual Ballots

If VxMarkScan is being used in a language other than English, the resulting ballot will be multi-lingual and feature the other language. All pieces of text that appear on the VxMarkScan ballot may have translations specified in the , which will then be used when printing the ballot.

hashtag
QR Code

The QR codes on VxMarkScan ballots are different than the in that they actually contain voter selections in addition to the ballot metadata. For full specifications on how metadata and selections are encoded, refer to the .

System Overview

The VotingWorks voting system (a.k.a. VxSuite) consists of four primary components:

  • VxAdmin: election setup and election results manager

  • VxMarkScan: ballot-marking device (BMD)

VxScan Polls Reports

hashtag
Polls Opened and Closed Reports

When polls open or close on VxScan, a tally report is printed. The tally report contains the tally results (pre-adjudication) of all ballots scanned at the scanner.

The tally report header contains the following information:

VxScan: precinct scanner

  • VxCentralScan: batch scanner

  • Voters mark paper ballots by hand or by using VxMarkScan to machine mark. Ballots are read and counted by tabulating devices (VxScan & VxCentralScan), which create cast vote records for adjudication and aggregation on VxAdmin. VotingWorks considers read and counted ballots as the same.

    An election begins with generating an election package and hand marked ballots using an external system.

    hashtag
    VxAdmin

    VxAdmin is where the election administrator performs election setup tasks and manages election results. At the beginning of an election, the user configures VxAdmin with an election package. Once configured, VxAdmin is used for two key election setup tasks:

    • Exporting a copy of the election package to USB drives with a digital signature. The election package is used to configure VxMarkScan, VxScan, and VxCentralScan, and it must be digitally signed by VxAdmin.

    • Programming role-based smart cards that will be used to authenticate on all machines. While the "System Administrator" role is election-agnostic, the "Election Manager" and "Poll Worker" roles are election-specific and cards must be programmed for every election.

    VxAdmin is later used to load, store, and aggregate cast vote records from the scanners. The results are available for review or export in several results formats. Election administrators can mark results as official, after which no new results can be added.

    • VxAdmin Function

    • VxAdmin & VxCentralScan Hardware

    hashtag
    VxMarkScan

    VxMarkScan is the system's ballot-marking device (BMD) that provides an accessible voting experience. At the beginning of an election, it is configured with an election package from VxAdmin. Once configured, a voter can make vote selections in various interaction modes according to their needs.

    The following input modes are supported:

    • Touch, using the touchscreen

    • Tactile, using the accessible controller

    • Limited Dexterity, using a sip-and-puff device or other dual-switch input

    The following output modes are supported:

    • Visual, with options to change color contrast and text size

    • Audio, with navigation instructions and contest details read to the user over headphones

    The voter can also adjust the language based on translations included in the election package.

    After the voter finishes their vote selections, VxMarkScan prints a machine marked ballot and presents it to the voter. The ballot is scanned (but not cast) so the interpreted results can be presented to the voter on-screen. After reviewing the ballot and confirming their selections, the ballot is cast and ejected into the attached ballot box. At a later time, depending on election procedures, the ballot will be removed from the ballot box for tabulation.

    • VxMarkScan Function

    • VxMarkScan Hardware

    hashtag
    VxScan

    VxScan is the system's precinct scanner. At the beginning of an election, it is configured with an election package from VxAdmin. The election package specifies the ballot layouts. The polls are opened by a poll worker after which casting ballots is allowed. Opening polls prints a tally report which is empty because no ballots have been scanned, a.k.a. the zero report.

    Voters cast ballots by inserting their ballots into the scanner in any orientation. After interpreting the scanned ballot, the scanner will drop the ballot into the ballot box and inform the voter that their ballot was successfully cast. During voting, VxScan continuously exports cast vote records to an attached USB drive.

    If the election is configured to support second-chance votingarrow-up-right and the ballot triggers a configured adjudication reason (e.g. it has an overvote), the scanner will hold the ballot while the voter is notified of the issues on their ballot. The voter then chooses whether to cast their ballot or return it to update or spoil.

    When polls are closed, the CVR export is completed and a polls closed report prints. The polls closed report includes the vote tallies of all ballots cast at the scanner while polls were open. Unlike the vote tallies eventually exported from VxAdmin, the vote tallies at VxScan do not contain any post-voting adjudication information such as write-in adjudication. The CVR export on the USB drive is then taken to VxAdmin for adjudication, aggregation, and reporting.

    • VxScan Function

    • VxScan Hardware

    hashtag
    VxCentralScan

    VxCentralScan is the system's batch scanner, often used to scan absentee or provisional ballots. At the beginning of an election, it is configured with an election package from VxAdmin. The election package specifies the ballot layouts.

    Ballots are inserted in the batch scanner's hopper and a batch scan is triggered from VxCentralScan. The ballots are scanned and interpreted in succession until the hopper is empty. If a ballot triggers a configured adjudication reason (e.g. it has an overvote), scanning will pause and the ballot will be displayed on screen, at which point the user can choose to tabulate the ballot anyway or remove it, untabulated.

    After scanning is complete, the user can export the cast vote records to a USB drive and take the USB drive to VxAdmin for adjudication, aggregation, and reporting.

    • VxCentralScan Function

    • VxAdmin & VxCentralScan Hardware

    Top level system diagram

    Election Seal

    The seal included in the election definition

    Ballot Title

    The title is either "Unofficial Test Ballot" or "Official Ballot" depending whether VxMarkScan is in test mode

    Election Metadata

    Includes the election title, election date, state, and county

    Ballot Metadata

    Includes the precinct name, the ballot style identifier, and the ballot identifier. The ballot identifier is a random UUID assigned by VxMarkScan.

    QR Code

    See QR Code

    Contest Title

    The contest title

    Selection

    The name of the candidate or label of the yes-no contest option that the voter selected

    Party

    The short party name associated with the selected candidate

    election definition's ballot strings
    QR codes on hand marked ballots
    Ballot QR Code Data Format
    English/Chinese VxMarkScan Ballot
    Title - Includes the type of the polls report and the name of the precinct, or "All Precincts" if VxScan is configured to accept ballots from all precincts
  • Subtitle - For primary elections, includes the full party name or "Nonpartisan Contests"

  • Election Info - The title, date, and location of the election

  • Timestamps - The first timestamp indicates when the poll status changed and the second indicates when the report was printed. In most cases these times are the same, but in some cases the report may be printed later.

  • Election ID - The election ID on the report is a concatenation of the ballot hash and election hash and specifies exactly which election definition and election settings that the report corresponds to

  • Certification Signatures - The space is provided for poll workers or election officials to sign the report in accordance with local statute.

  • For elections with multi-sheet ballots, counts per sheet are displayed in addition to the overall ballot count.

    Each candidate or contest option appears in a row below the contest header. Because results at VxScan are not yet adjudicated, all write-ins are grouped under the "Write-In" bucket (except unmarked write-ins, which are reported as undervotes until adjudicated at VxAdmin).

    As a rule, the sum of the number of votes for all candidates, the number of undervotes, and the number of overvotes will equal the number of total possible votes for the contest, which is the number of ballots times the number of selections allowed.

    hashtag
    Polls Paused and Resumed Reports

    When voting is paused or resumed, VxScan prints a report containing the ballot count. Tally results are never included. The header is structured in the same way as the polls opened and closed reports.

    Tally Reports

    hashtag
    Basic Structure

    The basic structure of the tally reports printed from VxAdmin is similar to the printed from VxScan.

    hashtag

    candidate votes + undervotes + overvotes = ballots * votes allowed

    Guidance for Test Labs

    This page covers guidance for test labs that isn't relevant for election workers.

    hashtag
    Power Cycling

    While test labs are free to run machines for long periods of time and naturally need to for tests like the 104-hour continuous operations test, we generally recommend powering down machines every couple of days. Rebooting a machine triggers necessary log file compression and rotation to save disk space. While some log files are compressed and rotated automatically on a daily basis, others are not in order to maintain the highest possible fidelity and are only compressed and rotated on reboot.

    Password and Credential Policies

    On VxSuite machines, there are no passwords for election administrators to use – only smart cards as described previously. The smart cards all use 256-bit elliptic-curve digital signatures, which makes them cryptographically strong. In addition, the PINs that gate usage of those cards follow the NIST recommendations for authentication – 6 digits long, randomly generated (as opposed to chosen by the user who might use a birthdate), and never a weak PIN like 000000.

    Filtered and Grouped Reports

    In addition to the full election report, VxAdmin exports reports filtered or grouped by the following dimensions:

    • Ballot Style

    • Precinct

    • Voting Method

    • Scanner

    • Batch

    • District (filtering only)

    When a report is grouped, the report is broken up into multiple sections each with their own filter. For example, if you were to group by "Voting Method," the resulting report would have a section filtered for precinct ballots only and a section filtered for absentee ballots only:

    First part of a grouped tally report
    Second part of a grouped tally report

    The filter for a given report section is indicated in the title of the report. If the report has more than one filter applied to it, the full details of the filter will be specified in a box below the title:

    Tally report with a complex filter

    Note that filters and groups can be combined.

    hashtag
    Manual Results

    If manual results have been added, they will be included in the tally report alongside the scanned results. For each contest, there will be three results columns: "scanned", "manual", and "total".

    Tally report with manual results

    hashtag
    Write-In Candidate Aggregation

    In order to prevent a long list of write-in candidates from making contest results difficult to read, VxAdmin tally reports consolidate write-in candidates if they're not relevant to the contest outcome. Relevant write-ins are included as "<Name> (Write-In)". Irrelevant write-ins are consolidated as "Write-In" or, if there are relevant write-ins in the list, "Other Write-In". Unadjudicated write-ins are always consolidated as "Unadjudicated Write-In."

    A write-in is deemed relevant if it must be listed for the reader to determine the winner(s) of the contest. In the middle example below, the single adjudicated write-in is consolidated because Natalie Portman is the winner regardless of the identities of the write-ins. In the last example, however, there are 31 adjudicated write-ins so it's possible that a write-in got more votes than Natalie Portman. The report then enumerates the write-ins with the highest vote totals until the "Other Write-In" count is smaller than the counts for all winners.

    Before adjudication
    Adjudication just started
    Adjudication almost finished

    polls opened and closed reports
    Full election tally report

    Election Package

    The election package contains all of the information that defines an election. VxAdmin is configured by inserting a USB drive and selecting an election package from the drive.

    After VxAdmin is configured, the election package can then be digitally signed and exported onto a USB drive in order to configure VxScan, VxCentralScan, and VxMarkScan. The digital signature verifies that the election package is legitimate. The other devices require that the signature is present. As a result, an election package from outside the system cannot be used to directly configure VxScan, VxCentralScan, or VxMarkScan.

    hashtag
    Election Package Contents

    The election package is a zip archive (a .zip file). The zip archive contains 6 files:

    • Election Definition (election.json)

    • App Strings (appStrings.json)

    • Audio IDs (audioIds.json)

    hashtag
    Election Definition

    The election definition file includes the information that defines the election and ballots, including but not limited to definitions for contests, ballot styles, precincts, parties, multi-lingual ballot translations, and ballot layouts. The system accepts two formats - the format or the . When using the Ballot Definition CDF, some features are not available.

    The election definition file is required to be present in the election package.

    hashtag
    App Strings

    The app strings file contains all voter-facing strings in the user interface and their translations. For example, at the beginning of the voter flow in VxMarkScan there is a button labelled, by default, "Start Voting." If the voter has set VxMarkScan to another language, however, the button will display the translation for that language specified in the app strings file. Additionally, the default English text can be overridden by specifying a different English value in the app strings file.

    In the case of specifying a Spanish translation and overriding the English translation for "Start Voting", which has an internal key of buttonStartVoting, the following values and overall structure would appear in the app strings file:

    Notes:

    • Voter-facing strings that appear on ballots (contest names, candidate names, the name of the jurisdiction, etc.) are not included in the app strings file because they are already included in the election definition.

    • The language codes in the app strings file are the for supported VxSuite languages: English, Spanish, Simplified Chinese, and Traditional Chinese.

    • The keys for the various user interface app strings (e.g. buttonStartVoting) are defined in VxSuite's .

    The app strings file is optional. If not provided, default English strings will be used.

    hashtag
    Audio IDs & Audio Clips

    The audio IDs file is a JSON file structured identically to the app strings file except that instead of containing text values for each voter string, it contains audio IDs for each voter string. Each audio ID corresponds to an entry in the audio clips file.

    Each row of the audio clips file contains one audio clip with relevant metadata. The audio itself appears as an MP3 file encoded in base 64. For example, a row representing an audio clip for the "Start Voting" button would appear as:

    Together, the two files allow specifying audio playback for any text read to a voter in audio mode, including both non-English translations and English overrides.

    The audio IDs and audio clips files are optional. If they are not provided, audio playback will be disabled.

    hashtag
    System Settings

    The system settings file contains settings which are not specific to an election definition but do impact machine behavior.

    • Authentication Settings

      • arePollWorkerCardPinsEnabled - When set to true, poll worker cards are created with PINs which are then required when authenticating.

      • inactiveSessionTimeLimitMinutes

    The system settings file is optional. If not provided, the following default settings will be used:

    hashtag
    Metadata

    The metadata file is a JSON file that contains a single key, version. In the current software version, the value will only ever be "latest". In other words, the metadata file is a JSON file with the contents:

    In future software versions, the "version" value will be used to differentiate versions of the election package that correspond to different software versions. For example, if a user flow is updated, a new app string may be added and the "version" value will indicate which app strings to expect.

    hashtag
    Ballot Hash and Election Package Hash

    There are two hashes for each election which are both critical to operation and security of each election.

    The ballot hash is the SHA256 hash of the election definition file and represents a snapshot of all election-specific data which determines the ballot, including contest definitions and ballot layout. Ballots must include a machine-readable version of the ballot hash (e.g. a QR code or a pattern of timing marks). When a ballot is scanned, the scanner checks to make sure the ballot has the expected ballot hash. The ballot hash from the ballot must match the ballot hash from the scanner's configured election definition.

    If any election content changes, the ballot hash will change, meaning the system will consider it to be a new election definition, and any ballots with a different ballot hash will not scan. The system's strict checking of the ballot hash prevents situations where a change to the election definition leads to ballots being miscounted (for example, if the order of two candidates is swapped). As a result, any changes to the election definition require reprinting all ballots.

    The election package hash is the SHA256 hash of the entire election package, which includes both the election definition and all other files. The election package hash is displayed on screen to election managers and system administrators. It allows the user to ascertain which election package was used to configure a machine. The election package hash is not used during ballot scanning.

    For example, imagine that an election administrator wants to change the audio clip for candidate's name. The audio clip is not a part of the election definition but it is a part of the election package, so the ballot hash remains the same while the election package hash changes. The election administrator can reconfigure VxMarkScan with an updated election package but does not have to reprint ballots.

    The election ID shown on screen and included in printed reports contains a shortened version of both the ballot hash and the election hash in the format: {ballot hash}-{election hash}. For example, with ballot hash 083e2e0afbb19191a4d2850562ddef050ff860b0d61acee15d3bb26954932941 and election hash db5c379b71accbf991e42ab23d26202f88b2539b6c69b814a0d3c8dc9f4072dc, the election ID would be: 083e2e0-db5c379. This enables identification of both the specific election package and election definition that a machine is configured with.

    hashtag
    Ballot Rotation

    Ballot rotation is specified by the defined candidate order in each ballot style as opposed to specifying a rule that the voting system should apply to a given list of candidates. The system supports tabulation of ballots with any type of candidate ordering. This enables flexibility for jurisdiction-specific ballot rotation rules that can be defined in the source system creating the ballot definition.

    Election officials can verify their ballot rotation configuration by configuring VxMarkScan, selecting different precincts (and by extension ballot styles), and confirming that the order of candidates differs per precinct as expected.

    Hand Marked Ballots

    VxSuite can tabulate a wide variety of ballot designs as long as they conform to the following requirements:

    1. Ballot size must be one of the available system options

    2. Ballot must include correctly formatted timing mark borders

    3. Ballot must include an appropriately positioned metadata QR code

    4. Ballot must use a specific bubble shape

    5. Ballot must adhere to

    hashtag
    Ballot Size

    All supported ballot sizes are 8.5 inches in width, but vary in height as specified in .

    These lengths correspond to the length specified in the within the election definition.

    hashtag
    Timing Mark Borders

    Every ballot must have timing mark borders on both front and back. The timing marks and page margins are strictly defined:

    Dimension

    As for number of timing marks, there are always 34 in the top and bottom borders, which has a 32 x 39 grid of possible bubble positions inside the timing mark border. The number of marks in the left and right borders varies based on the length of the ballot, and should be calculated by the formula (# inches * 4) - 3. For example, a letter-sized ballot (11 inches) should have 41 left and right timing marks whereas a legal-sized ballot (14 inches) should have 53 left and right timing marks.

    The timing marks must be aligned to the margins of the page and evenly spaced.

    hashtag
    QR Code Metadata

    The ballot must include a QR code which contains key metadata about the ballot.

    hashtag
    QR Code Content

    The QR code includes ballot metadata:

    • Precinct Index - corresponds to a precinct in the election definition

    • Ballot Style Index - corresponds to a ballot style in the election definition

    • Page Number - page number within the ballot style

    In addition, the QR code includes the ballot hash. The ballot hash ensures that the ballot was generated from the same election definition that will be used to interpret the ballot.

    For full specifications on how to generate readable QR codes, refer to the .

    hashtag
    Metadata QR Code Placement

    The interpreter looks for the QR code in the bottom-left corner of the ballot. The detection area is a square whose sides are 1/4 of the ballot width.

    hashtag
    Bubble Format

    In order to be interpreted correctly, bubbles must meet the following dimensions:

    Dimension
    Measurement

    hashtag
    Grid Coordinates

    The timing mark borders define an abstract grid that VxSuite uses to assign coordinates to positions on the ballot. In the election definition, bubble positions and other ballot regions are specified using these grid coordinates. The ballot grid is an XY grid with the origin in the top-left corner. For example, the coordinate (5, 3) would correspond to the following position on the ballot:

    Notes:

    • Coordinates correspond to the center of each timing mark

    • Coordinates specify the center of each bubble

    • Fractional coordinates are allowed

    hashtag
    Complete Example

    Below is a complete ballot that, when paired with the appropriate election definition, could be interpreted within VxSuite:

    Artifact Authentication

    When a VxSuite machine exports data to a USB for another VxSuite machine to import, the first machine digitally signs that data so that the second machine can verify its authenticity. We use this mechanism in two places in particular:

    1. To authenticate election definitions/packages — These configuration bundles are exported by VxAdmin and used to configure VxCentralScan, VxMarkScan, and VxScan.

    2. To authenticate cast vote records — These are exported by VxCentralScan and VxScan and imported by VxAdmin for tabulation.

    The exporting machine digitally signs the following message using its TPM private key:

    System Performance & Specifications

    This document covers supported capabilities and system limits that, alongside the System Overview, constitute the VxSuite Implementation Statement.

    hashtag

    hashtag

    System Security, Auditing & Logging

    hashtag

    hashtag

    Software Installation

    Software installation involves two steps:

    1. Generating software images via Trusted Build:

    2. Imaging machines with those images:

    Virt Manager - Network Access & Troubleshooting

    hashtag
    Disabling Network Access

    By default, newly created VMs have networking enabled. To ensure the offline VM does not have access to the internet, the networking link is disabled before the VM is ever used. This is accomplished by editing the VM's configuration (found in /etc/libvirt/qemu/offline.xml) and setting the link state to down. This functionality can be seen in the vxsuite-build-system repo, in .

    If an offline VM exists, the XML configuration file is updated to set the link state to down. After that, the offline VM is explicitly re-defined from this updated XML configuration file. These steps always execute, even if the network link state is already set to down.

    MESSAGE_FORMAT_VERSION + “//” + ARTIFACT_TYPE + “//” + ARTIFACT_CONTENTS

    It then outputs the following to a .vxsig file:

    SIGNATURE_LENGTH + SIGNATURE + SIGNING_MACHINE_CERTIFICATE

    The importing machine parses the above and verifies that the signing machine certificate in the .vxsig file is a valid certificate that is signed by VotingWorks, using the VotingWorks CA certificate installed on every machine. The importing machine then extracts the exporting/signing machine’s public key from this certificate, reconstructs the message, and verifies the signature. After this, the importing machine performs artifact-specific authentication checks, e.g., that the signing machine cert is a VxAdmin cert if the artifact is an election package.

    If verification fails on the importing machine, the importing machine will refuse to import the artifact. This provides protection against data tampering and/or corruption as data is transferred from one machine to another via USB drive.

    hashtag
    Code Links

    Refer to the following code links for more details:

    • https://github.com/votingworks/vxsuite/tree/v4.0.2/libs/autharrow-up-right — VxSuite authentication lib, a good starting point for all things authentication

    • https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/artifact_authentication.tsarrow-up-right — Artifact authentication logic

    • https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/cryptography.tsarrow-up-right — OpenSSL commands underlying various authentication and signing operations

    hashtag
    Paper Ballot Specifications

    hashtag
    Reliably Detectable Marks

    hashtag
    Processing Capabilities

    Supported Voting Variations & Languages
    System Limits
    hashtag
    Procedural and Operational Security

    hashtag
    Audit Procedure

    hashtag
    Logging

    hashtag
    Vulnerability Management

    hashtag
    Risk Assessment

    hashtag
    Hardware Criticality and Supplier Analysis

    System Security Architecture
    Physical Security
    Trusted Build
    Imaging Machines
    Test Ballot Flag - indicates whether the ballot is a test ballot or an official ballot
  • Ballot Type (Precinct, Absentee, or Provisional)

  • Timing Mark Width

    3/16 in.

    Timing Mark Height

    1/16 in.

    Page Margin (Top, Bottom)

    12pt (1/6 in.)

    Page Margin (Left, Right)

    5mm

    Width

    0.20"

    Height

    0.13"

    Border Radius

    0.7"

    Line Thickness

    1px (0.265mm)

    system limits
    Paper Ballot Specifications
    Ballot Layout
    Ballot QR Code Data Format
    Example of timing mark borders on letter-sized paper (scaled)
    The highlighted area must contain the metadata QR code
    Bubble example (not to scale)
    Valid ballot with timing marks, QR code, and bubbles

    Supported Voting Variations & Languages

    hashtag
    Supported Voting Variations

    • N-of-M contests

    • Yes/No contests

    • Partisan Primary Elections

      • The voting system itself does not have a concept of an open vs. closed primary as primary ballot styles are restricted to one party, but can support both types of primaries through procedurally restricting a voter to a given ballot style.

    hashtag
    Supported Languages

    • English

    • Spanish

    • Chinese (Simplified & Traditional)

    Voter-facing content in an election package can be translated to additional left-to-right languages and imported into VxSuite, but is not formally supported or tested by VotingWorks.

    Processing Capabilities

    The processing capabilities of the system are enumerated in the System Overview.

    Specifically, capabilities that may be bypassed or enabled by the user are configured in the system settings file within the Election Package.

    Imaging Machines

    This section walks through the steps to install a Trusted Build image on a VotingWorks component using vx-isoarrow-up-right.

    Note: If you are installing a VotingWorks application for use in an election, you are required to create a software installation record. The details of this software installation record can be found here: Software Installation Record Creation

    Audio Clips (audioClips.jsonl)

  • System Settings (systemSettings.json)

  • Metadata (metadata.json)

  • - Sets the number of minutes after which machines automatically lock due to inactivity.
  • numIncorrectPinAttemptsAllowedBeforeCardLockout- Sets the number of times that a PIN can be entered incorrectly before the user has to wait extra time to retry.

  • overallSessionTimeLimitHours- Sets the maximum number of hours for any session, regardless of activity.

  • startingCardLockoutDurationSeconds - Sets the number of seconds that the user is locked out from retrying a PIN after the number of failed attempts specified by numIncorrectPinAttemptsAllowedBeforeCardLockout. Each subsequent failed attempt triggers a lockout double the length of the previous lockout.

  • Scanning Thresholds

    • definite - Specifies the percentage of a bubble that needs to be filled in for the system to interpret it as a vote.

    • marginal - Specifies the percentage of a bubble that needs to be filled for the system to interpret it as a marginal mark that may need adjudication.

    • writeInTextArea - Specifies the percentage of the write-in area that needs to be filled in for the tabulators to consider it a write-in. This is only relevant for jurisdictions that allow unmarked write-ins i.e write-ins without an accompanying mark.

  • Adjudication Reasons

    • precinctScanAdjudicationReasons - Specifies the reasons that a ballot scanned at VxScan should be flagged for adjudication. Supported reasons are overvotes, undervotes, blank ballots, or unmarked write-ins.

    • centralScanAdjudicationReasons - Specifies the reasons that a ballot scanned at VxCentralScan should be flagged for adjudication. Supported reasons are overvotes, undervotes, blank ballots, or unmarked write-ins.

    • adminAdjudicationReasons - Specifies the reasons for a ballot to appear in the VxAdmin adjudication queue in addition to write-ins. Supported reasons are undervotes, overvotes, and marginal marks.

    • disallowCastingOvervotes - When set to true, scanners will always reject overvoted ballots. When set to false, VxScan will allow a voter to choose whether to reject or cast an overvoted ballot, and VxCentralScan will allow an election manager to choose whether to reject or tabulate an overvoted ballot.

    • allowOfficialBallotsInTestMode - When set to true, official ballots will not be rejected in test mode. The setting is for jurisdictions where testing must take place on official ballots.

  • Other

    • precinctScanEnableShoeshineMode - When set to true, VxScan will run in "shoeshine mode," which will scan the same ballot repeatedly. Instead of ejecting the ballot after scanning it, VxScan will move it back to the input tray and scan it again. This mode is used only for internal testing and certification testing.

    • castVoteRecordsIncludeRedundantMetadata - When set to true, scanners will include election and system metadata in each ballot's CVR as specified in the CVR CDF, rather than just including it once for the entire export. This extra information increases the size of the CVR export, degrading performance.

    • disableVerticalStreakDetection - Disables the warning when streaks are detected when scanning ballots (which indicates that the scanner needs to be cleaned). Used as a failsafe in case of erroneous warnings.

    • precinctScanEnableBallotAuditIds - Enables the VxScan feature to read ballot IDs from hand marked paper ballot QR codes, encrypt them, and export them to cast vote records (to be used for post-election auditing).

  • VxSuite Election Definition
    Ballot Definition CDF
    IETF language tagsarrow-up-right
    app strings catalogarrow-up-right
    Any VM cloned from this offline VM will also have a disabled network since those settings are inherited from the original VM.

    hashtag
    Troubleshooting

    Virt Manager uses a local bridge network to connect to VMs. If you receive an error when starting a VM that says "Error starting domain: Cannot get interface MTU on 'virbr0': No such device", run the following command in the terminal on the build machine:

    You should now be able to return to the VM and start it without issue.

    playbooks/virtmanager/clone-base-vm.yamlarrow-up-right
    sudo virsh net-start default
    {
      "en": {
        ...
        "buttonStartVoting": "Begin Voting",
        ...
      },
      "es-US": {
        ...
        "buttonStartVoting": "Empezar a votar",
        ...
      }
    }
    {
      "en": {
        ...
        "buttonStartVoting": "AUDIO_ID_1",
        ...
      },
      "es-US": {
        ...
        "buttonStartVoting": "AUDIO_ID_2",
        ...
      }
    }
    { "languageCode": "en", "id": "AUDIO_ID_1", "dataBase64": "YnV0dG9uU3..." }
    { "languageCode": "es-US", "id": "AUDIO_ID_2", "dataBase64": "DnX0eG6uY3..." }
    ...
    {
      "auth": {
        "arePollWorkerCardPinsEnabled": false,
        "inactiveSessionTimeLimitMinutes": 30,
        "numIncorrectPinAttemptsAllowedBeforeCardLockout": 5,
        "overallSessionTimeLimitHours": 12,
        "startingCardLockoutDurationSeconds": 15
      },
      "markThresholds": {
        "definite": 0.07,
        "marginal": 0.05,
        "writeInTextArea": 0.05
      },
      "centralScanAdjudicationReasons": [],
      "precinctScanAdjudicationReasons": [],
      "adminAdjudicationReasons": [],
      "disallowCastingOvervotes": false,
      "allowOfficialBallotsInTestMode": false,
      "precinctScanEnableShoeshineMode": false,
      "castVoteRecordsIncludeRedundantMetadata": false,
      "disableVerticalStreakDetection": false,
      "precinctScanEnableBallotAuditIds": false
    }
    {
      "version": "latest"
    }

    Reliably Detectable Marks

    Marks are determined valid and counted by the system if the amount of darker pixels in the bubble area exceeds a configurable "definite" mark threshold set in the Election Package system settings file. This mark threshold can be adjusted to have a stricter or looser interpretation of what is considered a valid mark. On both VxScan and VxCentralScan, the voting system does not process any marks as ambiguous. All marks are either valid or invalid.

    The recommended and default threshold is 7%. With this threshold setting, hand marked paper ballot interpretation detects a valid mark per the mark conditions described by VVSG 1.1.6-H.

    At this default threshold, marks such as a light dot, a fold through a bubble, a stray mark outside of the bubble, or a small line just on the corner of a bubble will be considered invalid. Marks such as a completely filled bubble, half filled bubble, or an X in a bubble will be considered valid.

    Examples of invalid and valid marks along with the score for that mark (in green) are shown below.

    The mark threshold set on a scanner can be checked by an election official at any point by viewing the readiness report for that device as described in Diagnostics (see also & in the user manual).

    hashtag
    Invalid Marks

    hashtag
    Valid Marks

    hashtag
    Marginal Marks

    The system also supports setting a marginal mark threshold for flagging ambiguous marks close to but not quite over the definite mark threshold. If a marginal mark threshold is set and marginal mark adjudication is enabled, the definite mark threshold can be increased without having to worry about completely missing marks.

    Basic Configuration Wizard

    If this is the first time that a VotingWorks application has been installed to a machine, the machine will boot into a basic configuration wizard. If the machine has been previously configured with a certified VotingWorks application of the same type, this wizard will be skipped.

    The majority of the steps are self-explanatory, but "Step 1: Set Machine ID" and "Step 4: Create Machine Cert" require some extra clarification.

    hashtag
    Setting Machine ID

    It is important that the machine ID be unique for each machine. Many machines have a physical placard on them indicating the machine ID. That is the ID that should be used here.

    hashtag
    Creating Machine Cert

    On VxAdmin, you'll first see a prompt to enter a jurisdiction:

    circle-info

    SLI should use co.sli

    Then, on all machines, you'll see this prompt:

    Insert a USB drive that you designate for this purpose. From here on out, we'll refer to this USB drive as the VxCertifier USB drive.

    After selecting the VxCertifier USB drive, a certificate signing request will be written to it. You'll then be prompted to:

    Because you'll be certifying your machine at your own facility as opposed to a VotingWorks facility, you won't be able to take the USB drive to VxCertifier, our VotingWorks certification terminal. We'll need to use a remote certification process instead.

    You'll need to remove the VxCertifier USB drive, find the "csr-<machine-id>.pem" file inside the "certs/" directory on it, and share that file with VotingWorks. This file does not contain any private information so can be shared over the internet, e.g., via email. VotingWorks will prepare a certificate given this "csr-<machine-id>.pem" file and send the certificate back to you, in the form of a "cert-<machine-id>.pem" file. This file, too, does not contain any private information so can be shared over the internet. You'll need to copy this "cert-<machine-id>.pem" file back onto the VxCertifier USB drive, placing it in the same "certs/" directory that we pulled the "csr.pem" from. Re-inserting the USB drive into the machine and pressing enter should allow you to proceed successfully.

    On VxAdmin, you'll be prompted to program your first system administrator card as a last step. Remember to record the displayed PIN. On other machines, no steps remain. You'll reboot into the app after this.

    Paper Ballot Specifications

    The following defines the minimal specifications for VxSuite paper stock. Ballot layout requirements are enumerated in Hand Marked Ballots and Machine Marked Ballots in the System Overview.

    hashtag
    Hand Marked Ballots

    VxSuite supports a wide range of paper for hand-marked paper ballot style printing within the following supported specifications:

    • Width: 8.5"

    • Length: 11", 14", 17", 19", 22"

    • Weight: 105-177gsm

    • Coating: uncoated

    • Opacity: >90%

    • Color: white or any pastel color ≥70 brightness. Contrast ratio of printed black text is 21:1 for white paper and will exceed 10:1 on other paper colors of specified brightness.

    • Watermarking: none

    • Ink: typical oil-based or soy-based inks are appropriate for printing presses; typical laser toner or inkjet ink are appropriate for smaller printers & copiers.

    • Folding: ballots should not be folded through bubbles.

    • Bleed-through: bleed through should not be present when using recommend paper weight (105-177 gsm) and marking method (ball point pen).

    • Margins: the paper margins listed below are required for proper timing mark interpretation and adequate space for VxCentralScan imprinting outside of the ballot selection area and timing marks:

      • Left/right: 5mm (0.19685 in)

      • Top/bottom: 12pt (0.16667 in)

    • Scale: 100% — all VotingWorks ballot PDFs must be printed at 100% scale. Any print scale deviation will render the ballot imprecisely.

    • Print Run Size: defer to your print vendor's established best practices for quality assurance. In the absence of a vendor recommendation, we recommend that print runs are a consistent size between 500 to 1,000 sheets — consistency eases ballot accounting and the moderate size allows for semi-frequent quality checks.

    hashtag
    Ballot Marking Device Ballots

    VxMarkScan requires a specific type of thermal paper ballot stock as required by the VSAP BMD 150 component:

    • Manufacturer: Mitsubishi

    • Model: Thermoscript TF 1467

    • Width: 8"

    TF 1467 paper is only provided in one configuration on white paper with a weight of 140gsm, an opacity greater than 90%, and thermal coating on one side. VxMarkScan expects the thermal side to be fully blank and therefore pre-printing attributes such as watermarking, ink, and margins are not applicable. Similarly, these ballots are only to be used with ballot marking devices and attributes specific to hand-marking such as folding and bleed-through are also not applicable. Printed text contrast ratio of blank ink on white paper is 21:1.

    Build Machine Configuration

    hashtag
    Build Machine Requirements

    • Operating system: Debian 12

    • RAM: 8GB minimum

    • Chip: x86-64 / amd64 CPU architecture, Intel i5 or higher

    • Storage: 250GB minimum

    hashtag
    Build Machine Configuration

    Debian 12 will need to be installed on the build machine. You can find detailed instructions for that process under . Once that is complete, we can install the VotingWorks build system, .

    Throughout the rest of this document, substitute <inventory-name> with the inventory provided by VotingWorks.

    At this point, you should have two separate VMs: debian-<inventory-name>-<apt-snapshot-date>-<debian-release-name>and online. You can confirm this by running:

    Imaging

    First make sure that you've prepared USB drives for imaging, following the instructions under Preparing USB Drives for Imaging. Then follow these steps:

    1. Power off the machine.

    2. Insert the vx-iso USB drive into the system. If this is a VxMarkScan or a VxScan, connect a keyboard as well. If there aren't enough ports available, use a USB hub as provided by VotingWorks.

    3. Power on the machine to begin booting vx-iso.

      1. By default, VotingWorks systems should boot from the USB. If not, you will need to select the USB drive from a BIOS or Boot Menu. For central system components, you can access the Boot Menu by pressing F9 during the boot sequence. For other components, please reach out to VotingWorks for assistance.

    4. Select "Install Image". You can navigate vx-iso with the keyboard. This option will be auto-selected after 30 seconds.

    5. If the machine already has Secure Boot keys installed, it should not prompt you to install keys. If it does for some reason, you should reach out to VotingWorks for assistance. Only if you know the keys need to be installed should you opt to install them.

    6. The application image(s) on the vx-iso USB drive will be displayed. Select the number that identifies the correct image. In the event there is only one image, it will be automatically selected.

    7. The imaging process will begin automatically after 10 seconds.

    8. Once imaging completes, remove the USB drive as prompted. The system will then automatically reboot.

    9. After rebooting, the system will perform an automatic encryption of the var filesystem. If Secure Boot was not enabled when the image was installed, you'll see a note about needing to enable Secure Boot. The machine will auto-boot you into the BIOS. Once Secure Boot has been enabled and the system reboots, the encryption process should complete successfully.

    10. The /var partition should encrypt and expand, followed by a reboot. If this is the first time that a VotingWorks application has been installed to a machine, you should find yourself in the . Proceed to that section. If the machine has been previously configured with a certified VotingWorks application of the same type, the will be skipped.

    Note: VotingWorks system software will be installed to the directory path: /vx/code/vxsuite

    The underlying storage for /vx/code/vxsuite will depend on the hardware type. By default, NVMe storage is used. In the event an NVMe storage device is not available, an eMMC storage device will be used.

    System Security Architecture

    This section describe the overall system security architecture of VxSuite and the measures taken to thwart attacks on the proper operation of elections on VxSuite.

    hashtag

    hashtag

    Write-In Adjudication Report

    The write-in adjudication report includes the results of all write-in adjudication organized by contest:

    The values in the contest table above are as follows:

    Field
    Description

    User Roles

    VxSuite has four authenticated user roles. Authentication is performed with JCOP4 Java Cards, a security-oriented type of smart card. Each card is programmed with a single role and, in most cases, a PIN for two-factor authentication. Details of the authentication system can be found here: .

    hashtag
    Poll Worker Role

    The poll worker role is the lowest privilege role for election day tasks at the precinct.

    The poll worker role allows a user to manage the polls on the precinct equipment, VxScan and VxMarkScan. On both devices, the poll worker card is used to open and close polls on election day. On VxMarkScan, the poll worker card is used to enable voter sessions. There are a few other actions enabled by the poll worker card - reprinting reports, powering down the machine, or checking the software hash - but overall the role is quite limited.

    Public Documents

    The VxSuite TDP is open-source and publicly available. The public documents required by VVSG are listed below:

    • Election Event Log Coding:

    • CDF Implementation:

    Maximum Tabulation Rate

    The maximum tabulation rate for batch-fed scanners is primarily limited by the hardware scanning speed limit for each central scanner model:

    • Ricoh fi-8170: 80 sheets per minute

    • Ricoh fi-7600: 100 sheets per minute

    The sheet per minute rate is reduced by the need to interpret ballot images. Ballot interpretation speed varies based on the following ballot variables:

    Online Phase

    1. Open virt-manager:

    1. Double-click the online VM.

    2. Press the start button ▶️.

    Cryptography

    hashtag
    Cryptographic Modules

    VxSuite v4 contains four distinct cryptographic modules:

    • Smart cards

    Software Installation Record Creation

    When installing VotingWorks applications that will be used in one or more elections, it is necessary to create a record of the software installation. There are multiple requirements, as described below.

    3.1.4-I.1 a unique identifier (such as a serial number) for the record; 3.1.4-I.2 a list of unique identifiers of storage media associated with the record; 3.1.4-I.3 the time, date, and location of the software installation; 3.1.4-I.4 names, affiliations, and signatures of all people present; 3.1.4-I.5 copies of the procedures used to install the software on the programmed devices of the voting system; 3.1.4-I.6 the certification number of the voting system; 3.1.4-I.7 list of the software installed as well as associated digital signatures and mechanisms for installation and verification on programmed devices of the voting system; and 3.1.4-I.8 a unique identifier (such as a serial number) of the vote-capture device or election management system (EMS) which the software is installed.

    To satisfy the above requirements, VotingWorks recommends following these best practices related to each requirement.

    3.1.4-I.1 - We recommend using the machine ID for this record, e.g. SC-11-004 If necessary, appending the install date and time can further ensure uniqueness, e.g. SC-11-004-20250325-1300

    Final Configuration

    We'll now clone the offline VM to prepare images for specific machine types, i.e., VxAdmin, VxCentralScan, VxMarkScan, and VxScan. We'll create one clone/VM per machine type.

    In the following steps, the vxadmin VM will be referenced, but these steps can be repeated for each machine type: vxcentralscan, vxmarkscan, and vxscan.

    1. To clone the offline VM, run the following command on the build machine:

    Verifying the Image Installed on a Machine

    hashtag
    Signed Hash Validation

    Once a machine has been imaged with a signed image, you can verify the system hash against the hash of what was built and signed during the Trusted Build process. To perform this verification, VotingWorks provides Signed Hash Validation.

    See for details.

    Note: On older releases (v4.0.1 and earlier), the Secure Boot signing process only output a SHA256 hash value. That hash value needs to be converted to a base64 encoded value to match what is provided by Signed Hash Validation. That can be accomplished with the following command:

    Offline Phase

    1. To create the offline VM with networking disabled, run the following command on the build machine:

    1. Open virt-manager if not already open:

    1. Double click the offline

    Preparing USB Drives for Imaging

    To install an image on a VotingWorks component, i.e., to image a machine, you need a vx-iso USB drive with one or more VotingWorks application images stored in the "Data" partition. There is also a "Keys" partition that can optionally contain VotingWorks Secure Boot public keys, necessary if a machine hasn't had these keys installed yet.

    USB drives used as vx-iso drives must be zeroed out before first use. This step will also ensure the USB drive is empty and no longer contains any previous data prior to use as installation media. You can zero out a drive with the following command, substituting /dev/sdX with the appropriate path to the USB you are using, e.g. /dev/sda

    Drives provided by VotingWorks are already initialized with this process and contain the appropriate vx-iso release for installing an application image. You will only need to ensure the appropriate application image(s) are copied to the vx-iso USB drive. If you are creating your own vx-iso USB drive, please contact VotingWorks for assistance.

    Trusted Build

    The VotingWorks build process consists of three distinct build phases: , , and . The build process uses an inventory definition containing all the necessary information for a Trusted Build. All three phases are executed within a separate virtual machine (VM) managed by the tool, running on a Debian 12 operating system.

    In the online phase, the build process utilizes a base Debian 12 VM with network access enabled. All necessary code repositories and build tools are securely retrieved for use during the offline phase.

    In the offline phase, the build process utilizes a clone of the online VM with network access disabled.

    In the final configuration phase, the build process utilizes clones of the offline VM to prepare images for specific machine types, i.e., VxAdmin, VxCentralScan, VxMarkScan, and VxScan.

    After completing the final configuration phase, an unlocked installation image has been created. While this image is not appropriate for production use, it can be used for testing.

    Preserving Voter Privacy

    There is a tension between the requirement that (a) voter privacy should be strongly protected, and (b) cast vote records should be continuously exported in order to ensure that they can be immediately available in the case of hardware failure. For example, if each scanned ballot naively results in the creation of a new CVR file on the USB drive with a timestamp, the order of CVRs is obviously preserved on the USB drive, as the file creation and modification timestamps reveal the order in which those CVRs were stored.

    To meet both requirements, VxScan performs some amount of "shuffling" every time a CVR is saved to the USB drive. Every time a ballot is cast and its CVR is saved to the disk, VxScan picks one or two CVRs already stored on the USB drive and updates their creation and modification time on the USB drive. This is the digital equivalent of taking one or two random ballots from a pile and bringing them to the top of the pile. Thus, if an attacker were to view the CVRs on the USB drive, they would not be able to determine the order in which those ballots were cast, because of this constant shuffling.

    Recall from that a single CVR is structured, on disk, as a directory that contains the JSON data of the CVR and the ballot images for that CVR. The VxScan operation performed to move a single CVR "up to the top of the pile" involves four steps:

    Networking

    All VxSuite components are blocked from connecting to any network. Thus, there is no networking in a VxSuite implementation. Our network design is secure by virtue of it being completely absent.

    Networking is disabled through several layers of defense:

    • Network drivers and known network connections are purged in the software setup process. See script.

    • Secure boot ensures that the hard drive is not modified, thus preventing software that isn’t part of the approved VotingWorks bundle from running.

    Safety, Security, Privacy, and Continuity of Operation

    The following article and linked related articles are intended to cover VVSG 2.0 3.1.2-A.4.

    hashtag
    Safety

    Per VVSG 2.0 8.1-K - Eliminating Hazards, devices associated with the voting system are certified in accordance with the requirements of UL 62368-1. See . VxSuite hardware is designed to eliminate hazards from shock, radiation, heat, and mechanical dangers when used and maintained in accordance with the .

    Defense-in-Depth and Least Privilege

    Beyond the application-level protections and system integrity assurances built to ensure that unauthorized access is thwarted and unauthorized software cannot be executed, VxSuite is also designed with defense-in-depth and least-privilege principles. This ensures that a failure of some defenses, due to unforeseen bugs or novel attacks, can be limited in its impact.

    hashtag
    Minimal Operating System

    VxSuite runs a modern, stripped down Linux installation with the minimum number of packages to reduce the attack surface of any unexpected partial penetration. The set of packages is manually curated by our team and specified in our installation manifests when building a base Linux image.

    Usability & Accessibility

    hashtag
    User Centered Design

    User centered design (UCD) is a design philosophy and process that prioritizes the needs, preferences, and behaviors of end users throughout the design and development process.

    VotingWorks implemented user centered design in the following ways:

    Secure Boot Signing

    To finalize an image for production use, it's necessary to sign the image with the VotingWorks Secure Boot keys so that the image can be used on a Secure-Boot-enabled machine. This process requires the use of sensitive keys and a passphrase that should only ever be known to and used by VotingWorks. Since the Trusted Build process is performed by a third-party vendor (SLI), a process to securely sign the image without compromising the keys or passphrase is needed. This document describes that process.

    hashtag
    Transferring an Unsigned Image from SLI to VotingWorks

    Once SLI has created a Trusted Build image, the image and its VM definition (an XML file) must be securely provided to VotingWorks. To transfer the image and definition, SLI will upload to a shared S3 bucket only accessible to SLI and VotingWorks. This access is controlled via IAM permission policies.

    Length: 11, 13.25"
  • Corner Cut: 16mm, 45° cut, top-right of thermal coated side

  • Ballot type

    • Ballot marking device ballots are slower to interpret than hand marked paper ballots.

  • Sheet length

    • Shorter (such as 11") ballots are faster to interpret than longer (such as 22") ballots.

  • Ballot content

    • Ballots with more contests and contests selections are slower to interpret.

  • Taking these limitations into consideration, batch scanners can be expected to scan approximately 50 sheets per minute for typical elections configurations.

    In addition to the sheet per minute rate of a given batch, the maximum tabulation rate is also limited by the maximum batch size for each scanner. Due to the paper weight range supported by VxSuite, VotingWorks recommends a smaller batch size than the original manufacturer recommendation:

    • Ricoh fi-8170: 30 sheets per batch

    • Ricoh fi-7600: 100 sheets per batch

    Finally, the maximum tabulation rate over the course of a day is limited by the daily volume limitations of each central scanner:

    • Ricoh fi-8170: 10,000 sheets/day

    • Ricoh fi-7600: 44,000 sheets/day

    VxAdmin / VxCentralScan TPM (same underlying hardware)

  • VxMarkScan TPM

  • VxScan TPM

  • OpenSSL software

  • All of the above are FIPS-compliant.

    hashtag
    Smart Cards

    VxSuite v4 uses NXP JCOP 4 Java Cards, specifically this model: https://www.cardlogix.com/product/nxp-jcop-4-java-card-3-0-5-classicarrow-up-right.

    These smart cards are FIPS140-2-certified: https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3746arrow-up-right.

    The applet that we run on the cards, OpenFIPS201arrow-up-right, is an implementation of the NIST 201 PIV protocol, which sits on top of FIPS140 cryptography. In the applet, all cryptographic operations are handled by the Java Card operating system, implemented by the NXP JCOP 4 card.

    hashtag
    VxAdmin / VxCentralScan TPM

    The VxAdmin / VxCentralScan HP uses an NPCT75x TPM 2.0 chip by Nuovoton.

    This chip is FIPS140-2-certified: https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4411arrow-up-right.

    hashtag
    VxMarkScan TPM

    The VxMarkScan board uses an SLB 9665 TPM 2.0 chip by Infineon.

    This chip is FIPS140-2-certified: https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/2959arrow-up-right.

    hashtag
    VxScan TPM

    The VxScan board uses an SLB 9670 TPM 2.0 chip by Infineon.

    This chip is FIPS140-2-certified: https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3492arrow-up-right.

    hashtag
    OpenSSL

    We use OpenSSL 3.0.9 and install the FIPS provider, per these instructionsarrow-up-right. In the basic configuration wizard run on first boot after imaging, we run the mandatory openssl fipsinstall command to ensure that the FIPS provider is configured correctly and OpenSSL is running in FIPS mode.

    This provider is FIPS140-2-certified: https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4282arrow-up-right.

    FIPS-compliance of all OpenSSL operations is guaranteed as follows:

    • FIPS compliance via hardware modules: For relevant operations, OpenSSL outsources cryptographic operations to the TPM 2.0 chip, and as noted above, all of our TPM 2.0 chips are FIPS-compliant.

    • FIPS compliance via software modules: For all other operations, OpenSSL uses the FIPS provider. Our OpenSSL configarrow-up-right guarantees this.

    hashtag
    Authentication vs. Encryption

    VxSuite does not use encryption to secure data (election definitions, CVRs) while in transit on USB drives because that data does not need to be confidential – and in fact trust in a voting system is better achieved by transparency of this data. In particular, CVRs stored on USB drives are not encrypted so that they can be viewed using any computer. This is by design.

    On the other hand, VxSuite strongly authenticates all data, which is critical. Thus, election definitions and CVRs are in plaintext on the USB drives that transfer them, accompanied by strong digital signatures, generated by signing keys stored in hardware TPMs.

    VxSuite does encrypt data at rest on machines' internal drives, specifically their /var partitions, per Protecting Critical Read-Write Data.

    hashtag
    Cryptographic Keying Material

    All digital signatures for authenticating election definitions and CVRs are generated using ECC 256-bit keys, that further use the NIST standard P-256 curve.

    All hashes – for generating election IDs, digesting data before signing, constructing the Merkle-tree hash for CVRs, and constructing the dm-verity system integrity hash – are generated using the NIST standard SHA-256.

    Encryption of disk partitions is done using AES with 256-bit keys in XTS mode.

    Secure Boot code signing uses RSA 4096-bit keys.

    3.1.4-I.2 - This should be the machine ID + the system drive the application was installed to. For example, a machine identified as SC-11-004 with the VotingWorks application installed to the /dev/nvme0n1 drive would use the record: SC-11-004-dev-nvme0n1

    3.1.4-I.3 - As described.

    3.1.4-I.4 - As described.

    3.1.4-I.5 - Include physical copies of the TDP install instructions or a link to the TDP install instructions for this release.

    3.1.4-I.6 - This is the EAC Certification Number, which can be found on the Certificate of Conformance for this VotingWorks application release.

    3.1.4-I.7 - Include a physical copy of the COTS Report or a link to the COTS Report that can be found in the Hash/Checksum Verification of Dependenciesdocumentation, specific to each VotingWorks application release.

    3.1.4-I.8 - We recommend using the serial number of the hardware device the VotingWorks application is being installed to. If that is not available, the same identifier used in 3.1.4-I.1 is recommended.

    Focus on Users: Worked to understand who the users are, including voters and election administrators. This involved conducting user research including: researching election laws and practices in different states, piloting the system to gather user feedback, and conducting feedback sessions with different types of users.

  • Iterative Design: VotingWorks created several prototypes and tested these through pilot projects in Mississippi and New Hampshire. We also conducted targeted user testing to gather feedback and refine the software and hardware based on that feedback.

  • Involvement of Users: From the beginning, VotingWorks incorporated user feedback sessions, pilots, and targeted testing to make sure all changes met the needs of the end user.

  • Multidisciplinary Collaboration: VotingWorks gathered feedback from not just election officials and voters, but also academics and other interested stakeholders.

  • Usability Testing: Finally, VotingWorks conducted formal usability and accessibility testing, as required by VVSG 2.0.

  • hashtag
    Federal Standards for Accessibility

    VotingWorks components are all designed and tested to applicable federal standards for accessibility including the version of Section 508 Information and Communication Technology (ICT) Final Standards and Guidelines [USAB18], in effect as of January 18, 2018, and the WCAG 2.0 Level AA checkpoints [W3C10] included in that standard.

    VotingWorks recommends that blind or low vision users of the central system components (VxAdmin, VxCentralScan) should utilize one of the following mobile applications (or equivalent) to navigate the central system applications and associated COTS hardware (central scanners, printers, laptops, etc.):

    • Be My Eyes (iOS / Android)

    • Seeing AI (iOS)

    • Lookout (Android)

    hashtag
    Usability and Accessibility Testing Reports

    hashtag
    VotingWorks Pollworker Testing Report VxSuitearrow-up-right

    hashtag
    VotingWorks UAT Report VxSuitearrow-up-right

    Basic Configuration Wizard
    Basic Configuration Wizard
    hashtag
    System Integrity

    hashtag
    Networking

    hashtag
    Password and Credential Policies

    hashtag
    Defense-in-Depth and Least Privilege

    hashtag
    Cryptography

    Access Control
    Artifact Authentication

    All poll worker cards are programmed at VxAdmin and are programmed for a specific election. They must be reprogrammed for every election. Poll worker cards may or may not require PINs depending on the value of arePollWorkerCardPinsEnabled flag in the system settings file within the election package.

    The poll worker role has no purpose on the central equipment, VxAdmin and VxCentralScan, and poll worker cards will be ignored on those devices.

    hashtag
    Election Manager Role

    The election manager role is a broad role for election officials to setup and operate the election.

    On the precinct equipment, an election manager card is used to configure the machines at the beginning of each election. This includes loading the election package, selecting a precinct for the device, and checking on consumables such as thermal paper for VxScan. At the end of an election, the election manager card can be used to unconfigure machines, re-export results, and export logs. In addition, system functions like setting date and time, turning on and off certain features, and accessing system diagnostics are available to election managers. The election manager card is not usually required at the precinct on election day, however, where the poll worker card should be sufficient for all election day tasks.

    On the central equipment, an election manager card is used to access core election management features. On VxAdmin, it is used to load, adjudicate, review, and export results. On VxCentralScan, it is used to operate the scanner and export results.

    All election manager cards are programmed at VxAdmin and are programmed for a specific election. They must be reprogrammed for every election. They alway have PINs, which change after reprogramming the cards for a new election.

    hashtag
    System Administrator Role

    The system administrator role is a powerful role for initial election setup and machine management. Unlike the poll worker and election manager roles, they are not tied to specific elections.

    On VxAdmin, a system administrator card is necessary to initially load an election package from an external system. System administrators can then program poll worker cards and election manager cards for a specific election. In that sense, the system administrator role is the gatekeeper for loading elections and creating users, and is strictly necessary for every election.

    On all devices, the system administrator role allows accessing a menu with powerful system actions. Many actions are shared with election managers - unconfiguring a machine or setting the date and time. Others are unique to the system administrator. For example, on precinct devices a system administrator can reset polls from a "closed" state to a "paused" state in case a poll worker accidentally closes polls prematurely.

    Additional system administrator cards can be programmed by a system administrator at VxAdmin. System administrator cards always have PINs. Because a system administrator card is necessary to program cards or set up elections to begin with, at least one pre-programmed card is initially provided with the voting system to bootstrap the jurisdiction's authentication.

    hashtag
    Vendor Role

    The vendor role is a role that only VotingWorks itself has access to. It allows booting into an administrative menu with options to update various system configuration files.

    hashtag
    Voter Mode

    While the authentication model only includes the four aforementioned roles, one can conceptually describe a "voter mode" on the precinct devices. On VxMarkScan, a poll worker must authenticate in order to initiate a voting session. Once initiated, the voter is able to make selections, navigate menus, and print their ballot. Once done voting, the machine leaves voter mode and once again requires authentication to start a voting session. On VxScan, voter mode is any time the polls are open and no other role is authenticated, during which a ballot can be inserted for tabulation.

    Access Control
    Ballot Definition: Ballot Definition CDF
  • Cast Vote Records: Cast Vote Records

  • Election Results Reporting: CDF ERR Export

  • Logging: Logging

  • Barcodes:

    • Ballot QR Code Data Format: Ballot QR Code Data Format

    • Signed Hash Validation QR Code: Signed Hash Validation

  • Audit Implementation: Audit Procedure

  • Logging
    For a final production image, an additional step is required to securely sign the installation image for use with Secure Boot enabled systems, described under Secure Boot Signing.
    online
    offline
    final configuration
    virt-managerarrow-up-right

    Copy the CVR directory contents:

    cp -r 4d6a9dad-e6d6-4a29-89bc-9ab915012b73/ 4d6a9dad-e6d6-4a29-89bc-9ab915012b73-temp/

    • Once copying completes, mark the new directory as complete:

    mv 4d6a9dad-e6d6-4a29-89bc-9ab915012b73-temp/ 4d6a9dad-e6d6-4a29-89bc-9ab915012b73-temp-complete/

    • Delete the old directory:

    rm -r 4d6a9dad-e6d6-4a29-89bc-9ab915012b73/

    • Rename the new directory:

    mv 4d6a9dad-e6d6-4a29-89bc-9ab915012b73-temp-complete/ 4d6a9dad-e6d6-4a29-89bc-9ab915012b73/

    This four-step operation ensures that:

    • All metadata for that CVR (parent directory and children files) is updated, leaving no trace as to when that CVR was first saved to disk.

    • If a failure occurs at any point, it is possible to recover completely without losing any data.

    hashtag
    Code Links

    Refer to the following code links for more details:

    • https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/backend/src/cast_vote_records/file_system_utils.tsarrow-up-right

    Cast Vote Records

    The network stack is disabled in the BIOS.

  • Wi-fi or bluetooth hardware is not present on the machines.

  • Ethernet ports are blocked.

  • As a final layer of defense, a firewall configurationarrow-up-right is defined to block any incoming or outgoing traffic in the event a connection was somehow created.

  • Because there is no networking, all electronic data transfer is air-gapped via USB drives.

    these lines in the setup-machine.sharrow-up-right

    Official Candidate Counts

    The count of all write-ins that have been adjudicated for official candidates in the election definition

    Write-In Candidate Counts

    The count of all write-ins that have been adjudicated for write-in candidates added at VxAdmin

    Invalid

    The count of all write-ins that have been marked as invalid

    hashtag
    Relationship to Tally Reports

    Before adjudication, write-ins are treated as votes for a generic write-in candidate and will appear in tally reports as "Unadjudicated Write-In." After adjudication, the new value will be reflected on tally reports:

    • When adjudicated for an official candidate, the write-in will be added to the official candidate count just as a regular vote for the candidate would be

    • When adjudicated for a write-in candidate, either:

      • The write-in will be individually listed if it is relevant to the results

      • The write-in will appear in the adjudicated write-in bucket if it is not relevant to the results

    • When invalid, the write-in becomes an undervote

    hashtag
    Unmarked Write-Ins

    Unmarked write-ins behave differently in relationship to the tally results because they cannot be considered a valid vote before adjudication. As a result, they are considered undervotes before adjudication. If an unmarked write-in is adjudicated as invalid, then tally results will not change. If an unmarked write-in is adjudicated for a candidate, the unmarked write-in is no longer an undervote and is added to the vote total for that candidate.

    Also note that, because the write-in adjudication report includes unmarked write-ins, the "Unadjudicated Write-In" count on tally reports may be less than the "Not Adjudicated" count on the write-in adjudication report. The initial difference is the count of unmarked write-ins.

    Total Write-Ins

    The count of all write-ins. If unmarked write-ins are being adjudicated, they will be included in this count

    Not Adjudicated

    The count of all write-ins that have not been adjudicated in the write-in adjudication interface yet

    Write-in adjudication contest results
    Enter a jurisdiction ({state-2-letter-abbreviation}.{county-town-etc}, e.g., ca.los-angeles or vx.test for test/demo machines):
    sudo virsh list --all
    Installing Debian 12 on VxBuild
    vxsuite-build-systemarrow-up-right
    hashtag
    vx-iso

    The system hash can also be computed from outside the application, using a vx-iso USB drive as described under Preparing USB Drives for Imaging. After booting from the drive, simply select the option to "Compute System Hash".

    echo HASH | xxd -r -p | base64
    Signed Hash Validation

    Once the VM has initialized, log in with username vx and password votingworks.

  • To ensure that the console displays correctly, select "View" > "Resize to VM".

  • In the VM terminal window, run the following commands:

    • You will be prompted for the sudo password.

    1. The online phase will take awhile to complete. Once it finishes, you can shut down the online VM:

    sudo virt-manager
    mkdir ~/code && cd ~/code
    git clone https://github.com/votingworks/vxsuite-build-system
    cd ~/code/vxsuite-build-system
    
    # Optional step if VotingWorks is doing development work in
    # vxsuite-build-system and the latest code in GitHub differs from the source
    # code provided to the test lab
    git checkout <relevant-vxsuite-build-system-tag>
    
    ./scripts/tb-run-online-phase.sh <inventory-name>
    This command creates a byte-for-byte clone of the offline VM, along with all settings, including network functionality disabled at the VM level.
    1. Open virt-manager if not already open:

    1. Double-click the vxadmin VM.

    2. Press the start button ▶️.

    3. From the menu, select "View" > "Consoles" > "Serial 1". (If you only see a blinking cursor, make the window active by clicking in it, then press Enter. You should see a login prompt.)

    4. Once the VM has initialized, log in with username vx and password votingworks.

    5. To ensure that the console displays correctly, select "View" > "Resize to VM".

    6. In the VM terminal window, run the following commands:

    1. You will be guided through several prompts.

    2. Select the number of the machine type that you intend to build.

    1. Type "N" when asked whether this image is for QA.

    1. Type "y" when asked whether this is an official release image.

    1. Set a password for the vx-vendor user. This password will not meaningfully be used as the vendor menu on a production image is only accessible via a vendor card.

    2. After the script finishes, the VM will reboot. You will see a console login prompt. In the VM menu, select "Virtual Machine" > "Shut Down" > "Shut Down". Close the VM window once shutdown is complete.

    3. You will now need to perform the Secure Boot Signingarrow-up-right process with VotingWorks. Once that process is completed, the VM and corresponding image will be ready for use with Secure Boot.

    At this point, you are ready to install the image. You can find those instructions in Imaging Machines.

    VM.
  • Press the start button ▶️.

  • Once the VM has initialized, log in with username vx and password votingworks.

  • To ensure that the console displays correctly, select "View" > "Resize to VM".

  • In the VM terminal window, validate that networking is automatically disabled in the offline VM using the following command:

    • This command should either time out or immediately error with a failure in name resolution.

    1. To execute the offline phase, run the following commands:

    1. Once the offline phase completes, the base VotingWorks application has been built. You can now shut down the offline VM:

    cd ~/code/vxsuite-build-system
    ./scripts/tb-create-offline-vm.sh
    hashtag
    Copying an image file to a vx-iso USB drive

    For this example, we will assume that you have a signed vxadmin image on the build machine. It will be located in the root user's home directory and be named vxadmin-signed.img.lz4

    We will also assume the USB drive is automatically mounted by the vx user, with the Data partition located at:

    As the vx user, first verify the USB is mounted at the path above. An easy way to test is with the following command:

    That command should return without an error. It may list one or more images if they were already on the USB drive. That's ok. (You can delete any existing images from the USB drive if you like, but it is not necessary.)

    Since the signed image file is located in the root user's home directory by default, we'll use that path. As mentioned earlier, we will use a vxadmin image for this example. That path would be:

    To copy the image to the USB drive, run the following command as the vx user:

    Once the copy and sync completes, you can eject the USB drive and remove it. It is now ready to image a machine. Repeat this process with any other vx-iso USB drives and VotingWorks image files as required.

    sudo dd if=/dev/zero of=/dev/sdX bs=8M && sudo sync
    /media/vx/Data
    hashtag
    DEP and ASLR

    The Linux OS makes use of data execution prevention (DEP) and address space layout randomization (ASLR). These exploit mitigation strategies provide a low-level layer of protection against a variety of vulnerabilities. We have verified that these mechanisms are active via the following commands:

    hashtag
    No Root User Access

    Once a VxSuite image is built, access for the root user is shut down and that shutdown is locked in via secure-boot verification of the root partition.

    hashtag
    Narrow Superuser Functions

    When a VxSuite function requires superuser access, that access is captured as a minimal shell script, and the appropriate VxSuite Linux user is granted sudo permissions on that shell script alone. For example, on a VxSuite production machine, no user has the ability to call the mount command. Instead, when mounting USB drives, we have crafted a shell program that is only capable of mounting and unmounting USB drives at the /media/usb-drive mount point, and the vx-services user is granted superuser privileges when calling that script only. The full script for this example is available at https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/usb-drive/scripts/mount.sharrow-up-right.

    hashtag
    Minimal Window Manager

    VxSuite runs a minimal window manager, Openbox, which is built to have very few capabilities. In addition, we configure Openbox so as to turn off all keyboard shortcuts and contextual menus. Even if an attacker were able to plug in a mouse or a keyboard, they would be unable to get very far.

    hashtag
    Compartmentalization of Permissions and Separation of Auth

    All processes that a user can directly interact with in VxSuite run as user vx-ui. The processes that access the smart card reader or perform data processing services run as user vx-services.

    The vx-services Linux user has a set of permissions allowing it to access the scanner, printer, and smart card reader. It is configured, like the root user, to not have a password, so no interactive user can log in as vx-services and utilize those privileges for nefarious purposes. The services that run under the vx-services user account offer their services over local HTTP, with well-formed semantics as to what actions they allow. The authentication status is checked on the backend, by vx-services, so actions can only be taken if a valid authentication session is open.

    Meanwhile, if a user were to break out of the constraints we've placed on the window manager and obtain a shell, that shell would run as vx-ui, which as the ability to call into services run as vx-services, but does not itself have the direct privileges of vx-services. Thus, an attacker that penetrates the first line of defense would remain severely thwarted in what they can do next.

    NOTE: For documentation purposes, we will use a Trusted Build image named vxadmin. Replace that with the appropriate image name, as necessary.

    Once SLI has configured their S3 access and created a Trusted Build image, they will need to upload the image and its configuration file. Additionally, hashes of each file will be generated so that SLI and VotingWorks can confirm files were not modified during the upload or download phases.

    On the SLI build machine:

    Once the SLI upload has completed, VotingWorks will download and verify the hash values of all files. On the VotingWorks secure build machine, while SLI observes:

    Once the VotingWorks download has completed and been verified, and the VM has been successfully defined, VotingWorks can proceed with its Secure Boot signing process, while SLI observes.

    hashtag
    Secure Boot Signing

    VotingWorks will boot the VM, change the vendor password, attach a virtual device containing our Secure Boot signing keys, and select the option to "Lock the System Down" from the vendor menu. When prompted, VotingWorks will enter the passphrase for the Secure Boot signing keys.

    When the process completes, the lock-down script displays the system hash in SHA256 and Signed Hash Validation (SHV) versions. These hashes will be provided to SLI/EAC for official verification of the image.

    hashtag
    Transferring a Signed Image from VotingWorks to SLI

    Now that the image has been securely signed, VotingWorks will upload the signed image for SLI to later download. While SLI observes, VotingWorks will run the following command on the VotingWorks secure build machine:

    Once this step has completed, SLI can download the files at their convenience. On the SLI build machine:

    Once SLI has completed the download, and hashes have been validated, the compressed image and signature can be provided to EAC for official use. At any point after submission to EAC, election officials and VotingWorks can verify the image hash as described under Verifying the Image Installed on a Machine.

    Insert a USB drive into the machine. Press enter once you've done so.
    Remove the USB drive, take it to VxCertifier, and bring it back to this machine when prompted. Press enter once you've re-inserted the USB drive.
    sudo apt install -y git
    mkdir ~/code && cd ~/code
    git clone https://github.com/votingworks/vxsuite-build-system
    
    cd ~/code/vxsuite-build-system
    ./scripts/tb-initialize-build-machine.sh <inventory-name>
    ./scripts/tb-clone-images.sh <inventory-name>
    sudo shutdown -h now
    sudo virt-clone -o offline -n vxadmin --auto-clone
    sudo virt-manager
    cd ~/code/vxsuite-complete-system
    ./setup-machine.sh
    Welcome to VxSuite. THIS IS A DESTRUCTIVE SCRIPT. Ctrl-C right now if you don't know for sure what you're doing.
    Which machine are we building today?
    
    1. VxAdmin
    2. VxCentralScan
    3. VxMarkScan
    4. VxScan
    Is this image for QA, where you want sudo privileges, terminal access via TTY2, and the ability to record screengrabs? [y/N]
    Is this additionally an official release image? [y/N]
    sudo virt-manager
    ping -c2 google.com
    cd ~/code/vxsuite-build-system
    ./scripts/tb-run-offline-phase.sh <inventory-name>
    sudo shutdown -h now
    ls /media/vx/Data/
    ~root/vxadmin-signed.img.lz4
    sudo cp ~root/vxadmin-signed.img.lz4 /media/vx/Data/ && sudo sync
    # For DEP, verify that the nx flag is set on CPUs
    grep -m1 ' nx ' /proc/cpuinfo
    
    # For ASLR, verify that the output of this is 1 or 2, not 0
    cat /proc/sys/kernel/randomize_va_space
    sudo su -
    /home/vx/code/vxsuite-build-system/scripts/sb-unsigned-upload.sh vxadmin
    sudo /home/admin/code/vxsuite-build-system/scripts/sb-unsigned-download.sh vxadmin
    sudo /home/admin/code/vxsuite-build-system/scripts/sb-signed-upload.sh vxadmin
    sudo su -
    /home/vx/code/vxsuite-build-system/scripts/sb-signed-download.sh vxadmin
    hashtag
    Security

    The system's provisions for security are detailed in the System Security, Auditing & Logging section.

    hashtag
    Privacy

    The provisions for voter privacy on VxScan are described in Preserving Voter Privacy. The provisions for voter privacy on VxMarkScan are described in .

    hashtag
    Continuity of Operation

    hashtag
    Error Recovery

    The voting system is designed to recover from errors as gracefully as possible. Displayed error messages, as enumerated in the error message sections in the , are written to guide users to address the error. If the user encounters a recoverable error, the error message will instruct them to how to properly continue operation. For example if a smart card is inserted backward, the message will prompt the user to insert it correctly. If the user encounters an unrecoverable software error, the error message will prompt the user to restart the machine. The vast majority of problematic software states are resolved by a restart. After restarting, operation can continue.

    hashtag
    Machine Replacement

    If a machine is damaged to the point of being inoperable, a replacement machine of the same type can be used. For larger customers, VotingWorks recommends that customers buy and maintain their own backup machines. For smaller customers, VotingWorks can provide replacement machines. If a replacement takes place in the middle of an election, users can take the following steps to substitute equipment:

    • VxScan - Switch to scanning on the replacement VxScan and, at the end of the election, aggregate the cast vote records from both the damaged and replacement VxScans.

    • VxMarkScan - Voters should start new voting sessions on the replacement VxMarkScan.

    • VxCentralScan - The document scanner can simply be swapped. If the laptop is damaged and cast vote records were never exported, the scanned ballots should be re-scanned with the replacement laptop.

    • VxAdmin - If the laptop is damaged, the laptop should be reconfigured with the election package and any cast vote records should be reloaded from the various USB drives.

    hashtag
    Paper Processes

    VxSuite is ultimately a paper-based voting system and in the case of multiple overlapping failures, a part or the whole of the election can be transitioned to run on paper. If VxScan is damaged, ballots can be deposited in a ballot box and scanned later on VxCentralScan. If VxCentralScan is damaged, ballots can be fed into VxScan. If all scanners are damaged, ballots can be hand-counted.

    Eliminating Hazards

    Ballot Definition CDF

    The election definition within the election package can be a JSON Ballot Definition CDF Version 1.0 file. The full specification is defined by NIST and can be accessed on their websitearrow-up-right.

    hashtag
    VxSuite CDF Implementation

    VxSuite accepts the Ballot Definition CDF Version 1.0 as defined by NIST without any data extensions. VxSuite requirements differ from the NIST CDF schema only in the following respects:

    • Some fields not required in the NIST CDF are required in VxSuite

    • Some enumeration values are more restricted in VxSuite than in the NIST CDF

    • Some classes and attributes are ignored in VxSuite

    The exact VxSuite schema is defined as a which is derived from the . The differences between the two are documented in the below tables.

    hashtag
    Required Class Attributes

    CDF Class
    VxSuite Attribute Requirements

    hashtag
    Restricted Enums

    CDF Enum
    Allowed Values

    hashtag
    Ignored Classes and Enums

    CDF Entity

    hashtag
    Ignored Class Attributes

    CDF Class
    Ignored Attributes

    hashtag
    VxSuite CDF Conversion

    When importing a Ballot Definition CDF file, attributes will be mapped to the and used across the system in the exact same way.

    hashtag
    Attribute Mappings

    Ballot Definition CDF Attribute
    VxSuite Election Definition Attribute

    hashtag
    Translations

    Most attributes in the Ballot Definition CDF that could require translation are defined with the CDF InternationalizedText class which allows specifying variants for each language. InternationalizedText maps directly onto VxSuite's . When an InternationalizedText attribute is mapped to a ballot string, the English version is used as the default which will appear on reports and administrator interfaces while the translations are maintained in the election definition for multi-language experiences on voter devices.

    hashtag
    Geographies

    The Ballot Definition defines all geographies as GpUnits, whereas the VxSuite Election Definition defines various geographies.

    Some geographies must exist in the Ballot Definition CDF file to be used in VxSuite. There must be one GpUnit of type state and one of type county to populate the relevant metadata on the .

    Any GpUnit of type precinct is mapped to a .

    Any GpUnit with an associated contest is mapped to a .

    hashtag
    VxSuite CDF Limitations

    Because VxSuite does not utilize any data extensions to the Ballot Definition CDF, some information cannot be included when using the Ballot Definition CDF. The missing information creates some limitations when using the Ballot Definition CDF when compared to the format:

    • Contest term descriptions (e.g. “2 years”) will always show up in English because there is no field in the CDF for internationalized term descriptions

    • The full party name will be displayed for each candidate on VxMarkScan (e.g. “Democratic Party” instead of “Democrat”) because the CDF only has one attribute for party name. In contrast, the VxSuite format supports two separate fields, one for the full name and one for showing on the ballot.

    • When adjudicating write-ins, the highlighted contest option area will be set to a default because there is no field in the CDF for this parameter.

    Diagnostics

    All VxSuite components have a diagnostics interface accessible to system administrators and election managers that allows a user to monitor or test key components. Diagnostic information is shown to the user and can be exported as a PDF readiness report.

    When a test is performed, the system logs the result and creates a diagnostic record which includes the outcome of the diagnostic, pass or fail. The outcome and date of the most recent diagnostic is displayed on the readiness report. One possible use case of the readiness report is to run all diagnostics before an election and then produce a readiness report that confirms all tests passed.

    hashtag
    Common Diagnostics

    hashtag
    Storage

    Retrieves the current amount of disk space used and disk space available for the application. The displayed total disk space will not be as large as the actual disk because some space is reserved for the system. The disk space usage will not always return to 0% after clearing election data because the database may not have liberated that disk space back to the operating system, but the space will be reused once more election data is loaded.

    hashtag
    Battery

    For components with internal batteries - VxAdmin and VxCentralScan - the operating system is polled for battery status. The application will report the current charge level and whether or not the battery is currently charging.

    hashtag
    Uninterruptible Power Supply (UPS)

    For components that operate with an external UPS - VxMarkScan, VxScan, and VxCentralScan - there is a test flow for the user to confirm that the UPS is connected and fully charged.

    hashtag
    Configuration

    hashtag
    Election Identifier

    If there is an election configured on the machine, it will display the election title and hash.

    hashtag
    Ballot Styles

    For precinct equipment, the list of ballot styles will include only those appropriate for the current precinct configuration. For central equipment, the list of ballot styles will be all ballot styles in the election. The languages for each ballot style are also enumerated.

    hashtag
    Precinct

    For precinct equipment - VxScan and VxMarkScan - the currently configured precinct will be shown, if any.

    hashtag
    Mark Thresholds

    For scanners - VxScan and VxCentralScan - the currently configured mark and write-in area thresholds will be shown. The thresholds reflect what was set in the system settings.

    hashtag
    VxAdmin Diagnostics

    hashtag
    Printer

    The toner level and any alerts from the printer are displayed, such as sleep mode, paper jams, or hardware malfunctions. The user may perform a test print, which will send a mock report to the printer. The user inspects the printed document and confirms whether the test print was successful or failed.

    circle-info

    User Manual Reference:

    hashtag
    VxCentralScan Diagnostics

    hashtag
    Batch Scanner

    The user may perform a test scan, which requires that a blank white sheet of paper be scanned. The scanned image is broken up into small cells and each cell is checked for the percent of black pixels after binarization. If that percent is more than slightly over 0%, that cell is flagged and the entire diagnostic fails. The goal of the diagnostic is catch any defects in the scanned images, such as streaking produced by a dirty scanner.

    circle-info

    User Manual Reference:

    hashtag
    VxScan Diagnostics

    hashtag
    Embedded Scanner

    The user may perform a test scan, which requires that a blank white sheet of paper be scanned. The scanned image is broken up into small cells and each cell is checked for the percent of black pixels after binarization. If that percent is more than slightly over 0%, that cell is flagged and the entire diagnostic fails. The goal of the diagnostic is catch any defects in the scanned images, such as streaking produced by a dirty scanner.

    The test scan process is identical to that for VxCentralScan, and the images above apply.

    hashtag
    Thermal Printer

    The user may test the printer by printing a test page. After the print, the user must indicate whether the page printed successfully or not. The diagnostic available in the diagnostics interface is identical to that which election managers are encouraged to run after loading paper, and the outcome is recorded in either case.

    The diagnostics page will also display details about any printer errors if the printer is in an error state.

    hashtag
    Speaker

    The user may test the speaker by triggering the chime sound and confirming whether they heard the chime or not.

    circle-info

    User Manual Reference:

    hashtag
    VxMarkScan Diagnostics

    hashtag
    Printer-Scanner

    The user may perform a test of the printer-scanner which mocks the ballot flow during a voting session:

    1. User loads thermal paper

    2. Mock ballot is printed onto paper

    3. Mock ballot is scanned and presented in the front input tray

    4. Mock ballot is ejected into the ballot box

    A successful test indicates that the printer and scanner can properly produce and handle ballots during a voting session.

    hashtag
    Accessible Controller

    The user may perform a test of the accessible controller which validates that each button on the controller is producing the expected signal. The flow guides the user through pressing each button.

    hashtag
    PAT Input

    The user may perform a test of the PAT input, which is simply confirms that a PAT device can be successfully calibrated as it would be during a voting session.

    hashtag
    Front Headphone Input

    The user may perform a test of the front headphone input by connecting headphones and triggering a chime. The user must indicate whether they heard the chime or not, corresponding to a pass or fail respectively.

    circle-info

    User Manual Reference:

    Audit Procedure

    VxSuite can be audited using post-election audits, including a ballot-comparison or batch-comparison risk-limiting audit, or an image audit.

    hashtag
    Ballot-Comparison Risk-Limiting Audit

    In a ballot-comparison risk-limiting audit, the goal is to compare, for a random sample of the cast ballots, the paper ballot and the corresponding cast-vote record. The specifics of sample selection and risk-limit calculation are out of scope for this document – VotingWorks Arlo or other RLA tool may be used for this purpose.

    To enable a ballot-comparison risk-limiting audit, VxSuite provides:

    • imprinting of ballots on VxCentralScan, with a unique identifier of the form <BATCH-ID>_<SEQUENCE-NUM>

    • cast-vote records including the field BallotAuditId which matches the imprinted identifier

    Then, to run a ballot-comparison risk-limiting audit with VxSuite:

    1. scan all ballots with VxCentralScan and the imprinter module on the Ricoh scanner. See .

    2. store ballots by batch, recording the batch ID displayed on VxCentralScan display. Storing ballots in the order they were scanned is helpful for later retrieval, but not strictly necessary since the sequence numbers printed on the ballots can be used to recover the proper order.

    3. export CVRs from all the VxCentralScan's

    Alternatively, unique identifiers may be added by VxScan — see for the associated audit procedure.

    hashtag
    Batch-Comparison Risk-Limiting Audit

    In a batch-comparison risk-limiting audit, the goal is to compare, for a random sample of ballot batches, the hand tally of that batch with the corresponding batch tally. The specifics of sample selection and risk-limit calculation are out of scope for this document – VotingWorks Arlo or other RLA tool may be used for this purpose.

    To enable a batch-comparison risk-limiting audit, VxSuite provides:

    • Tallies partitioned by scanner and/or by batch in VxAdmin

    • Ballot counts by scanner and by batch in VxAdmin

    Then, to run a batch-comparison risk-limiting audit with VxSuite:

    1. scan ballots either with VxScan or VxCentralScan. No need to use imprinting for VxCentralScan.

    2. store ballots by batch – where a batch in VxCentralScan is indicated by the batch ID on screen, and a batch in VxScan is the entire set of ballots scanned by a single VxScan over the course of the election. Order of the ballots need not be maintained in either case.

    3. export CVRs from all VxCentralScans and gather the CVRs on USB drives from all VxScans

    hashtag
    Image Audits

    In an image audit, various risk-limiting audit procedures are used, but instead of physically retrieving the ballots to audit, the scanned image of the ballot is used.

    VxSuite supports image audits very simply – every VxScan and VxCentralScan produces images of the scanned ballots that can be immediately associated with the interpreted CVR. Thus, the protocols defined above for ballot-comparison and batch-comparison audits can be used, with the following simplification:

    • imprinting is unnecessary

    • instead of "retrieving a ballot", simply look up the image files corresponding to the CVR ID and interpret on screen

    System Integrity

    The foundation of our system integrity solution is the TPM (described in greater detail under Cryptography).

    Our design for system integrity maps closely to that of ChromeOS:

    1. The hard drive is partitioned such that executable code lives on the read-only partition /, and only /var and /home are mounted read/write for configuration, logs, and working data like scanned ballot images.

    2. The read-only partition is verified by , which generates a hash tree of all the raw partition blocks, culminating in a single hash root for the entire read-only filesystem.

    3. The kernel boot command line includes the dm-verity hash root as an argument, ensuring that Linux halts if the read-only partitions are not successfully verified against this hash root.

    4. The BIOS is configured to only boot a properly signed bootloader+kernel+command-line, with public keys managed by VotingWorks and configured in the BIOS as secure boot keys. The bootloader+kernel+command-line that we want is set up as the default boot option in UEFI.

    5. The private key described previously in is generated in the TPM and bound to Platform Configuration Registers (PCRs) that include the BIOS, the Secure Boot public keys, and the bootloader+kernel+command-line. Thus, this private key is only usable if the machine boots appropriately sanctioned source code with a hard drive whose read-only partitions are unmodified.

    As a diagram:

    The integrity of the overall system is ensured because:

    • Any change in the executable portion of the hard drive will be detected when dm-verity checks the hard drive blocks against its stored hashes.

    • Any change in the hashes stored on disk will be detected against the mismatched root hash, present in the kernel boot command line.

    • Any live changes to the read-only portion of the drive, even while the machine is already booted up, will be detected the moment Linux tries to read those modified blocks, as all disk reads are live-checked against the hashes.

    Thus, if the system boots, it means that the hard drive corresponds, by hashing, to the expected value that we baked into the bootloader+kernel+command-line and signed. If the system does not boot due to a failed cryptographic boot validation, it may be indicative of malware, so the user should make note of the error message and contact VotingWorks.

    The only time that the system hash is expected to change is after a software update, which involves completely reimaging the machine per the process laid out in .

    hashtag
    Hard Drive Partitioning

    Our system is configured so that /var, /tmp, and /home are mounted read-write, and / for everything else is mounted read-only. This requires writing logs and other runtime-generated VotingWorks data, e.g., scanned ballot images, to /var. Variable system configuration, e.g. timezone information, also needs to be redirected to /var. A USB mount point is pre-created at /media/vx/usb-drive.

    hashtag
    Protecting Critical Read-Write Data

    In addition to locking down the / partition, the /var partition is encrypted and authenticated using dm-crypt. This ensures that, even if an attacker removes the physical hard drive and connects it to a different CPU, they cannot read or modify the contents of the /var partition in an attempt to make the VxSuite component behave differently.

    Furthermore, as an extra layer of defense, every individual VxSuite component instance uses a unique random encryption key for its /var partition. Thus, if an attacker were to break the encryption on one VxSuite machine, they would have gained no advantage in penetrating a second machine. This is ensured through rekeying of the /var partition encryption on first boot of a VxSuite component.

    hashtag
    Signed Bootloader and Kernel

    With Secure Boot, UEFI passes control to the bootloader only if the bootloader is appropriately signed. Then, the bootloader passes control to the kernel. We choose to bundle the bootloader, kernel, and command line that is used to run the kernel all as one, and to present that to the UEFI as the single executable whose signature should be verified before running. The three are combined into a single object file, along with the dm-verity root hash. This single object file is signed by VotingWorks secure boot private keys.

    hashtag
    Secure Boot

    Every VotingWorks machine’s BIOS is configured with VotingWorks secure boot public keys, and the BIOS is configured to require Secure Boot. Thus, only a properly signed object file can serve as bootloader.

    hashtag
    Mounting USB Drives

    When mounting USB drives, VxSuite always mounts them using standard Linux mount configuration options that makes files on the USB drive NOT executable. This further protects from any unauthorized software running, even in a transient fashion.

    Ballot Count Reports

    Ballot count reports contain ballot and ballot sheet counts, not contest results.

    If there are multi-sheet ballots in the election, the sheet counts (e.g. "Sheet 1", "Sheet 2") can be added to the report in the ballot count report builder by selecting "Sheet" as a Report By dimension. The total ballot count is always defined as the first sheet count.

    If there are manual results, the manual ballot count will always be displayed separately from the scanned ballot count, and the total of the two will also be displayed.

    When grouping is applied in a ballot count report, each group corresponds to a row in the table. In the following example, the ballot counts are grouped by both precinct and voting method:

    Ballot count report

    The following metadata columns may appear in a ballot count report table in order to specify groupings:

    Header
    Values

    Filters apply to the entire report. Simple filters are shown in the title, while complex filters are listed in a box below the title.

    VxScan Unique Identifiers

    VxScan supports generating a unique audit identifier for each cast paper ballot. During a post-election audit, auditors can use these audit IDs to match a ballot to its corresponding cast vote record.

    hashtag
    Overall Process

    1. A serial number is added to each hand-marked paper ballot. This serial number is encoded in the ballot's metadata QR code.

    2. VxScan generates a random secret key when configured with an election package.

    3. When a ballot is cast, VxScan generates a unique audit ID for the ballot by randomizing the ballot's serial number using AES-256. It adds the randomized audit ID to the CVR.

    4. After polls are closed, an election manager saves the secret key from VxScan.

    5. During a post-election audit, an election official with access to the VxScan secret key derandomizes the audit IDs in the CVRs using any tool that implements VotingWorks's publicly specified derandomization logic, as documented in . For convenience, VotingWorks has deployed a proof-of-concept tool for this step in VxDesign.

    6. Auditors compare the derandomized audit IDs to the serial numbers encoded in the ballot QR codes, pairing CVRs with their corresponding physical ballots for a ballot-comparison audit.

    hashtag
    Ballot Serial Numbers

    At the point of election definition and ballot design, the QR code on each paper ballot is encoded with an optional Ballot ID value as defined in .

    If using VxDesign as the source ballot creation system, one can automatically generate unique ballot PDFs with sequential serial numbers encoded in each QR code. Before exporting an election package and ballots, check the box labeled "Generate audit IDs for ballots" and enter the number of audit IDs or serial numbers to generate.

    hashtag
    Randomized Unique IDs

    When configured with an election definition, VxScan generates a random secret key that it uses to randomize the ballot serial numbers as unique identifiers in the cast vote record. When ballots are cast and cast vote records are created, VxScan randomizes the ballot's serial number using AES-256 and adds this randomized unique ID to the BallotAuditID field in the CVR. See for the complete CVR file format.

    hashtag
    Saving VxScan Secret Key

    An election manager can save the VxScan secret key to a USB drive through the following steps:

    1. Authenticate using an election manager smart card

    2. Navigate to the CVRs and Logs screen in the election manager menu

    3. Select Save Ballot Audit ID Secret Key

    hashtag
    Derandomizing Audit IDs in CVRs

    The unique IDs generated by VxScan can be derandomized using standard AES-256 decryption with the secret key and CVRs generated from the same VxScan. This procedure can be incorporated into any tool that implements VotingWorks's publicly specified derandomization logic, as documented in .

    For convenience, VotingWorks has deployed a proof-of-concept tool for this step in VxDesign. Under the "Export" tab for any election is a "Decrypt CVR Ballot Audit IDs" section. Copy and paste the value of the secret key from the "ballot-audit-id-secret-key.txt" file on the USB drive that you saved the secret key to. Then locate the relevant CVR directory on your VxScan USB drive. From the root of the USB drive, navigate into <election-specific-folder>/cast-vote-records/. Pick out the relevant directory, e.g., machine_0000__2025-07-25_11-44-45, and zip it. In VxDesign, click "Select CVR Export Zip File" and upload the ZIP file that you just prepared. VxDesign will output a new ZIP file titled "decrypted-cvrs.zip" containing a copy of each CVR file with the derandomized ID, i.e., the ballot serial number, as the file name. For example, the CVR for ballot serial number 1 will be saved in the file 1.json.

    hashtag
    Comparing Derandomized IDs to Physical Ballots

    Auditors can use the the public to identify the original serial number encoded on a given paper ballot and map that to the CVR for that ballot based on file name. The ballot selections on the physical ballot can then be compared to the selections recorded in the CVR.

    For convenience, VotingWorks has implemented a QR code scanning website meant to be accessed on a smartphone: . When pointed at a valid VotingWorks paper ballot QR code, the website will display the parsed contents of that QR code, including the ballot serial number. The website refers to the ballot serial number, if present, as the "Ballot ID" as you can see in the screenshot below.

    Risk Assessment

    This risk assessment reviews threats and vulnerabilities identified in:

    • VxSuite hardware, including VxCentralScan, VxAdmin, vxMark, and VxScan. Also included are any items and peripherals needed to operate the equipment listed above (e.g., USB drives, scanners, printers).

    • VxSuite software and source code

    • VotingWorks internal communication and operation support systems.

    This assessment was conducted following the framework outlined in NIST Special Publication 800-30 - Guide for Conducting Risk assessments.

    For additional information on how physical, technical, and operational controls work together to meet the requirements of VVSG 14.1-C.1-4, please refer to , specifically:

    Please also refer to the , notably the documentation.

    [PDF]

    [Excel]

    Hash/Checksum Verification of Dependencies

    The VotingWorks build system, vxsuite-build-systemarrow-up-right, utilizes many different tools to install, configure, and build VotingWorks applications. To ensure the integrity of the build system and tools used, all third-party tools are verified against known hashes, checksums, or digital signatures. This appendix provides a description of the mechanism used to verify each tool and any additional resources those tools may be responsible for providing during the build process.

    In addition to verifying third-party tools against known hashes, checksums, and digital signatures during the build process, a report of COTS tools, with applicable hashes/checksums, is provided to the VSTL for independent verification and is available herearrow-up-right. These tools are defined within the vxsuite-build-systemarrow-up-right for each release of VotingWorks applications, and only those tools are installed during builds.

    APT

    Debian's package manager, apt, is built on a secure framework described here: SecureAptarrow-up-right.

    The VotingWorks build process relies on this fundamental tool to install many of the system level tools required to build our applications. As an added measure of security, all packages are pinned to specific versions to ensure a consistent build environment over time.

    To further ensure that consistent versions of dependencies and transitive dependencies are used, we create our own VotingWorks-hosted apt snapshot to pull from.

    pip

    Python's package manager, pip, does not verify package integrity by default. However, secure installation is possible via the method described here: .

    The VotingWorks build process implements the above method in the script. The required packages are listed, along with their hash, in unique requirements files based on the operating system version and architecture. You can see an example here: .

    RubyGems

    Ruby's package manager, gem, does not verify package integrity by default. However, the official gem repository provides SHA256 checksums for hosted packages. You can see an example here: .

    The VotingWorks build process requires the version and SHA256 checksum for any installed gems. Once the gem file has been downloaded, it is checked against this checksum to verify its integrity. You can see that checksum verification in the rubygems playbook here: .

    Rust

    By default, Rust is installed over an active internet connection. Since that method is not available during the offline phase of the VotingWorks build process, we use a standalone, offline installer binary provided by Rust. To verify the integrity of the installer, the downloaded file is verified against the officially published checksum that can be found in each version's official manifest. You can see that checksum verification in the rust playbook here: .

    Cargo

    Cargo is the Rust package manager. It provides secure installs via the combination of a manifest listing packages and their versions, along with a lock file containing the checksum for each package. That method is described here: .

    Node

    Node is typically installed via package managers like apt, or via a direct install from a specific version. We do not install Node via apt since we explicitly version it. As a result, we download the appropriate installer from the official Node repository. That downloaded file is then checked against the officially provided checksum. You can see that checksum verification in the node playbook here: .

    npm

    npm is the default Node package manager. It is installed as part of the Node install previously described.

    Packages installed via npm are checked against the officially provided checksums for each package. You can see that checksum verification in the node playbook here: .

    pnpm

    pnpm is another package manager for the Node ecosystem. It is installed via npm as previously described to ensure its integrity.

    Packages installed via pnpm use a lockfile: pnpm-lock.yaml. This lockfile includes the version and checksum to verify integrity when packages are installed during the build process. In addition, the VotingWorks build process explicitly requires the use of --frozen-lockfile to ensure that only the packages explicitly required are installed.

    Yarn

    Yarn is another package manager for the Node ecosystem. It is installed via npm as previously described to ensure its integrity.

    Packages installed via yarn use a lockfile: yarn.lock. This lockfile includes the version and checksum to verify integrity when packages are installed during the build process. In addition, the VotingWorks build process explicitly requires the use of --frozen-lockfile to ensure that only the packages explicitly required are installed.

    Signed Hash Validation

    Signed Hash Validation provides end users with a way to verify that a VotingWorks machine is running authentic unmodified VotingWorks software.

    The machine preps a payload consisting of the following, with 1//shv1// as a prefix and # as a separator:

    • System hash

    • Software version

    • Election ID

    • Current timestamp

    The machine signs that payload with its TPM private key and then bundles the following together, with ; as a separator:

    • Payload

    • Payload signature

    • Machine cert

    This combination is displayed as a QR code. Putting this all together, the QR code contains:

    This QR code can be scanned at . The site parses the QR code and performs the following verification:

    • Verifies the machine cert using the root VotingWorks cert.

    • Extracts the machine's public key from the machine cert.

    • Uses that public key to verify the payload signature against the original payload. If this verification succeeds, we can be confident that the machine possesses the TPM private key that pairs with the public key in the machine cert.

    After completing the above verification, displays a success indicator alongside the payload components and the machine ID as extracted from the machine cert. These attributes can be matched against what's displayed on the machine.

    Machine UX
    Web UX

    hashtag
    QR Code Specifications

    Signed Hash Validation QR codes are with .

    hashtag
    Code Links

    Refer to the following code links for more details:

    System Limits

    hashtag
    Election Definition Limits

    Limit Type
    Per
    Value

    Ballot Interpretation

    Ballot interpretation begins with the front and back images of the ballot transmitted from the scanner. Once the images are available to the application, it starts by trying to interpreting the ballot as a .

    The interpreter first crops the image received from the scanner and converts the grayscale image from the ballot into binary images using . Otsu's method computes a dynamic black and white threshold that allows the interpreter to filter out differences due to tinted paper or light streaking.

    Before trying to make sense of the ballot, the interpreter checks the images for vertical streaks. Vertical streaks likely indicate some sort of smudge or debris in the scanner that could interfere with the ballot image. The interpreter looks for columns of black without gaps, excluding the edges of the ballot which may be black simply from the way the scanner creates images.

    If a streak is detected, the interpreter exits and surfaces the error to the application which will alert the user.

    VxCentralScan Function

    VxCentralScan is the system's batch scanner which enable election managers to efficiently scan large batches of ballots.

    hashtag
    Configuration

    VxCentralScan is configured with a signed exported from VxAdmin. The election definition includes the ballot layouts necessary for interpreting ballots and the system settings which indicate what type of ballot issues (e.g. overvotes) require adjudication. After the election package is loaded by an authenticated election manager, no further configuration is required.

    Audio Visual & Display Screen Settings

    hashtag
    Electronic Display Screen Specifications

    The voting system features three electronic display screens - on VxScan, on VxMarkScan, and an identical screen on the laptops for VxAdmin and VxCentralScan. All screens are in conformance with 8.1-A's requirements for electronic display screens.

    • All screens include anti-glare technology to prevent distinct virtual images from appearing on the screen (8.1-A.1.a)

    pip: Secure installsarrow-up-right
    tb-install-ansible.sharrow-up-right
    Debian 12 x86 pip requirementsarrow-up-right
    FPM 1.15.1arrow-up-right
    rubygems.yamlarrow-up-right
    rust.yamlarrow-up-right
    Cargo.toml vs. Cargo.lockarrow-up-right
    node.yamlarrow-up-right
    node.yamlarrow-up-right
    use VxAdmin to aggregate CVRs, adjudicate write-ins, and generate final tallies
  • aggregate tallies and CVRs at the audit jurisdiction level, most often the State

  • input the CVRs and tallies into a risk-limiting audit tool

  • the RLA tool will generate a sample of ballots to audit

  • retrieve the selected ballots by batch ID and sequence number

  • enter the interpretation of those ballots into the RLA tool

  • the RLA tool will either declare the audit successful or require an escalation. The RLA tool will ultimately declare the election a success or call into question how ballots were interpreted.

  • use VxAdmin to aggregate CVRs, adjudicate write-ins, and generate final tallies
  • produce ballot counts by scanner and by batch on VxAdmin – these are effectively contest totals by batch files in auditing language.

  • aggregate tallies and ballot manifests at the audit jurisdiction level, most often the State.

  • input tallies and ballot manifests into the RLA tool

  • the RLA tool will generate a sample of batches to audit

  • retrieve the batches and recount them by hand – usually only for one or two contests, as directed by the audit procedure

  • enter the hand-count batch tallies into the RLA tool

  • the RLA tool will either declare the audit successful or require an escalation. The RLA tool will ultimately declare the election a success or call into question how ballots were interpreted.

  • VxScan Unique Identifiers
    Imprinting

    Precinct

    The name of the precinct

    Ballot Style

    The internal identifier of the ballot style

    Party

    The short name of the party, e.g. "Democrat". Included by default if the ballot style is included, in a primary

    Voting Method

    "Precinct", "Absentee", or "Provisional"

    Scanner ID

    The serial number of the scanner. Included by default if the batch is included

    Batch

    The label for the batch, or "Manual Tallies" for manually entered data

    Ballot count report with a complex filter

    GpUnit

    • At least one GpUnit must be defined with the type "state"

    • At least one GpUnit must be defined with the type "county"

    Office

    Term is required

    OptionPosition

    Sheet is required

    OrderedContest

    Physical is required and must have a minimum length of 1

    Party

    Abbreviation is required

    PhysicalContest

    PhysicalContestOption is required and must have a minimum length of 1

    PhysicalContestOption

    ContestOptionId is required

    ReportingUnit

    Name is required

    Term

    Label is required

    LatLng

    OfficeGroup

    OfficeTermType

    OrderedHeader

    PartyContest

    PartyOption

    PartyPreferenceContest

    PartyRegistration

    Person

    RetentionContest

    Schedule

    ShortString

    SpatialDimension

    SpatialExtent

    StraightPartyContest

    StraightPartyRuleset

    TimeWithZone

    VoteVariation

    CandidateOption

    ExternalIdentifier, SequenceOrder

    Election

    ContactInformation, OtherType

    Office

    ContactInformation, Description, ElectionDistrictId, ExternalIdentifier, FilingDeadline, IsPartisan, OfficeHolderPersonIds

    OrderedContest

    OrderedContestOptionIds

    Party

    Color, ContactInformation, ExternalIdentifier, IsRecognizedParty, LeaderPersonIds, LogoUri, PartyScopeGpUnitIds, Slogan

    ReportingUnit

    AuthorityIds, ContactInformation, ElectionAdministration, ExternalIdentifier, IsDistricted, IsMailOnly, Number, OtherType, PartyRegistration, SpatialDimension, TotalSubUnits, VotersRegistered

    Term

    EndDate, StartDate, Type

    Party.id

    Party.id

    Party.Name

    Party.name

    Party.Name

    Party.fullName

    Party.Abbreviation

    Party.abbrev

    Contest.id

    Contest.id

    Contest.BallotTitle

    Contest.title

    Contest.ElectionDistrictId

    Contest.districtId

    CandidateContest.VotesAllowed

    CandidateContest.seats

    CandidateContest.ContestOption.IsWriteIn

    CandidateContest.allowWriteIns

    CandidateContest.PrimaryPartyIds

    CandidateContest.partyId

    Office.Term.Label

    CandidateContest.termDescription

    Candidate.id

    Candidate.id

    Candidate.BallotName

    Candidate.name

    CandidateOption.EndorsementPartyIds

    Candidate.partyIds

    BallotMeasureContest.FullText

    YesNoContest.description

    BallotMeasureContestOption.id

    YesNoContestOption.id

    BallotMeasureContestOption.Selection

    YesNoContestOption.label

    BallotStyle.ExternalIdentifier.Value

    BallotStyle.id

    BallotStyle.GpUnitIds

    BallotStyle.districts, BallotStyle.precincts

    BallotStyle.OrderedContent

    BallotStyle.orderedCandidatesByContest

    BallotStyle.PartyIds

    BallotStyle.partyId

    BallotStyle.Language

    BallotStyle.languages

    BallotFormat.ShortEdge

    BallotLayout.width

    BallotFormat.LongEdge

    BallotLayout.height

    OrderedContest.ContestId

    GridPosition.contestId

    PhysicalContestOption.OptionPosition.Sheet

    GridPosition.sheet

    PhysicalContestOption.OptionPosition.Side

    GridPosition.side

    PhysicalContestOption.OptionPosition.X

    GridPosition.column

    PhysicalContestOption.OptionPosition.Y

    GridPosition.row

    PhysicalContestOption.ContestOptionId

    GridPositionOption.optionId

    PhysicalContestOption.ContestOptionId

    GridPositionWriteIn.writeInIndex

    PhysicalContestOption.WriteInPosition.X

    GridPositionWriteIn.writeInArea.x

    PhysicalContestOption.WriteInPosition.Y

    GridPositionWriteIn.writeInArea.y

    PhysicalContestOption.WriteInPosition.W

    GridPositionWriteIn.writeInArea.width

    PhysicalContestOption.WriteInPosition.H

    GridPositionWriteIn.writeInArea.height

    Seal images are not supported in the CDF, so no seal will be shown in association with the election.

    BallotDefinition

    • BallotFormat, Election, GpUnit, and Party are required

    • BallotFormat and Election must have a length of 1

    • GpUnit must have a minimum of length 1

    BallotMeasureContest

    • BallotTitle, ContestOption, and FullText are required

    • ContestOption must have a length of 2

    BallotStyle

    • ExternalIdentifier is required and must have a length of 1

    • Language must have a minimum length of 1

    CandidateContest

    • BallotTitle and ContestOption are required

    • ContestOption must have a minimum of length 1

    • PrimaryPartyIds must have a length of 1 if it exists

    CandidateOption

    CandidateIds must have a length of 1

    Election

    BallotStyle, Contest, and ExternalIdentifier are required and all must have a minimum length of 1

    ElectionType

    general, primary

    ReportingUnitType

    county, precinct, split-precinct, state, other

    ActivationContest

    ActivationOption

    AnnotatedString

    AnnotatedUri

    BallotMeasureType

    CandidatePreElectionStatus

    Coalition

    ContactInformation

    DayType

    ElectionAdministration

    GeoSpatialFormat

    BallotDefinition

    IsTest, Notes, OfficeGroup, Person, TestType

    BallotMeasureContest

    Abbreviation, BallotSubTitle, ContStatement, EffectOfAbstain, ExternalIdentifier, HasRotation, InfoUri, OtherType, OtherVoteVariation, PassageThreshold, ProStatement, SequenceOrder, SummaryText, TotalSubUnits, Type, VoteVariation

    BallotMeasureOption

    ExternalIdentifier, SequenceOrder

    BallotStyle

    ImageUri, Purpose

    Candidate

    CampaignSlogan, ContactInformation, ExternalIdentifier, FileDate, IsIncumbent, IsTopTicket, PartyId, PersonId, PreElectionStatus, ReadName

    CandidateContest

    Abbreviation, BallotSubTitle, ExternalIdentifier, HasRotation, NumberElected, NumberRunoff, OtherVoteVariation, RanksAllowed, SequenceOrder, TotalSubUnits, VoteVariation

    Election.ExternalIdentifier

    Election.id

    Election.Type

    Election.type

    Election.Name

    Election.title

    Election.StartDate

    Election.date

    GpUnit.id

    County.id, Precinct.id, District.id

    GpUnit.Name

    JSON schema in the vxsuite repositoryarrow-up-right
    original NIST schemaarrow-up-right
    VxSuite Election Definition
    ballot strings
    Election
    Precinct
    District
    VxSuite Election Definition

    Hours

    Election.state, County.name, Precinct.name, District.name

    Election

    1,000

    Contests

    Election

    1,000

    Ballot Styles

    Election

    1,000

    Candidates

    Contest

    100

    Vote For

    Contest

    50

    Characters

    Name, Title, Label

    100

    Characters

    Proposition Description

    10,000

    hashtag
    Component Limits

    hashtag
    VxAdmin

    • The total number of CVRs that can be imported is limited by the total disk space on the laptop (~200GB). The exact number of CVRs depends ballot size, ballot selections, tabulator used (VxScan or VxCentralScan), and other factors that determine expected CVR size.

    hashtag
    VxCentralScan

    • The total number of ballots scanned is limited by the total disk space on the laptop (~200GB). The exact number of ballots depends on ballot size, complexity, and selections made that influence determine the CVR and ballot image sizes.

    • VxCentralScan is limited by the batch scanner maximum tabulation rate: Maximum Tabulation Rate

    hashtag
    VxMarkScan

    • VxMarkScan only supports 8" x 11" and 8" x 13.25" ballot sizes as specified in Paper Ballot Specifications.

    • VxMarkScan ballot styles are limited to 25 contests.

    • A contest allows voting for n out of m candidates/choices. The general limits for n and m are listed in the above table: n = Vote For per Contest and m = Candidates per Contest.

      • On VxMarkScan, for any one contest, n is limited to 25 (lower than the general limit), and m is limited to 100 (the same as the general limit).

      • Take the sum of n across all contests on a ballot style to be N and the sum of m across all contests on a ballot style to be M. On VxMarkScan, N is limited to 75, and M is limited to 135.

    • Each VxMarkScan write-in is limited to 40 characters. The sum of write-in characters across all contests on a VxMarkScan ballot is limited to 60.

    • The ballot box supports up to 200 ballots before needing to be cleared.

    • VxMarkScan can activate, mark, verify, and cast up to 20 ballots per hour. Exact rate depends on time spent by user marking and verifying a ballot before casting.

    • VxMarkScan has a maximum available disk space of 9GB.

    hashtag
    VxScan

    • The ballot box supports up to 3000 ballots in the main compartment before needing to be cleared.

    • The ballot box auxiliary compartment supports up to 100 ballots before needing to be cleared. Ballots longer than 19" must be folded.

    • Total ballots scanned for a given VxScan configuration are limited to 10,000 ballots. This limit is set based on the disk space available on specified external disks to ensure adequate disk space in the case of needing to re-sync CVRs.

    • Ballot tabulation rate depends on election content / ballot length. A typical 11" ballot sheet is scanned and tabulated in 3 seconds.

    • An user can feed a ballot sheet every 10 seconds. At that feeding rate, the maximum tabulation rate is 360 sheets per hour.

    hashtag
    Hand Marked Paper Ballots

    In addition to the design requirements specified in Hand Marked Ballots, ballots are constrained by the following limits.

    hashtag
    Bubble Positions

    VxSuite hand marked paper ballot interpretation supports fractional grid coordinate positions, which enable bubble positions to be placed anywhere within the timing mark grid. However, the density of bubbles on a given ballot is limited to the total number of timing mark grid intersections to ensure accurate interpretation.

    For example, an 11" ballot has a 32 x 39 timing mark grid. The QR code and the footer typically occupy the bottom two rows of bubbles so the usable grid is 32 x 37, giving a maximum number of ballot positions of 1,184 per page or 2,368 per sheet. The maximum number of ballot positions increases for longer ballots due to the longer grid.

    Candidates Per Contest

    The total number of candidates per contest is limited by ballot design requirements restricting contest options to one column and one page (7.3-B.1). Therefore, the maximum number of candidates in a contest is the maximum number of bubble positions in a column. For a 22" ballot, there is a maximum of 83 possible bubble positions in a column. The maximum number of candidates per contest may be lower than 83 when accounting for instructional text and contest information in the ballot design.

    Precincts

    Election

    1,000

    Candidates

    VxSuite User Manual - v4
    VxSuite User Manual - v4

    Any change in the kernel boot command line will be detected in two ways:

    • First, the TPM won’t unseal secrets since a change in the command line changes one of the PCR values, which means that the TPM’s policy check will fail.

    • Second, the system won’t even boot at all because the changed command line invalidates the signature on the bootloader+kernel+command-line, and UEFI will refuse to execute the now-improperly signed bootloader+kernel+command-line.

    dm-verityarrow-up-right
    Access Control
    Imaging Machines
    Networking
  • Password and Credential Policies

  • Defense-in-Depth and Least Privilege

  • Cryptography

  • Procedural and Operational Security

  • Trusted Build

  • Access Control
    Artifact Authentication
    System Integrity
    Risk Assessmentarrow-up-right
    Risk Assessmentarrow-up-right
    VxSuite User Manual - v4
    Because the TPM private key will only sign data if the system hash is correct, per System Integrity, we can further be confident that the software on the machine is authentic and unmodified.

    https://check.voting.worksarrow-up-right
    https://check.voting.worksarrow-up-right
    Model 2 QR codesarrow-up-right
    Level H error correctionarrow-up-right
    https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/signed_hash_validation.tsarrow-up-right
    The interpreter then identifies the timing mark grid. It searches for all vertical line segments around the edges of the ballot and joins adjacent line segments to form shapes. The shapes are filtered and scored according to how closely they resemble timing marks. The interpreter then looks for patterns of three timing marks resembling the corners of the grid. If the four corners cannot be identified, the interpreter exits. Once the corners are identified, the interpreter looks for the rest of the timing marks along the lines between the corners.

    Before proceeding with interpretation, the interpreter calculates the distance between horizontal timing marks to verify the scale at which the ballot was printed. The expected distance is derived from the specifications for Hand Marked Ballots. If the timing marks are too close together, the interpreter rejects the ballot — ballots must be printed at full scale to be interpreted safely.

    The interpreter will then search the bottom left and top right corners of the image for a QR code. Since ballots have QR codes in the bottom left corner, the location of the QR code determines the correct orientation of the ballot and the interpreter can flip the image right-side up if necessary:

    QR code search
    Correctly oriented ballot

    The QR code includes ballot metadata - precinct, ballot style, election hash, ballot mode - but no vote information (see Hand Marked Ballots). Up until now, the two sides of a ballot have been interpreted in parallel. At this point, the QR code metadata on the front and back are compared to ensure that they match to form a valid ballot. The ballot information from the QR code indicates which ballot layout from the election definition that the ballot conforms to, including the position of all the bubbles, contests, and write-in areas.

    Now the interpreter inspects the locations of all ballot bubbles to see how filled they are. Note that bubbles are not necessarily aligned with timing marks because they can be defined in fractional grid coordinates. Each bubble is compared with a bubble template to distinguish voter marks from the bubble itself and is scored accordingly. In the images below, the orange score is the "match score", or the confidence that the bubble was found correctly. The greenish score is the "mark score", or the amount that the bubble's area is filled in. An empty bubble would receive a mark score of 0% or close to it–typically less than 1%.

    Ballot bubble scores

    The bubble mark scores are later compared against the mark thresholds in the system settings to determine whether the voter made an indication that should be counted. The recommended default definite mark threshold is 7%. Setting too low of a threshold may result in stray marks or ballot folds to be considered as marks. Setting too high of a threshold may result in reasonable voter marks not being detected. While ballot instructions should recommend voters fully fill in the bubbles, at a threshold of 7% the system will detect most voter marks that pass through the bubble.

    Valid Marks
    Invalid Marks

    After bubbles are scored, the interpreter will then determine the location of the contest options relative to the grid. The write-in areas are defined in the election definition relative to the contest option areas. The write-in areas are then scored, similarly to the bubbles. This step only occurs in jurisdictions allowing unmarked (unbubbled) write-ins because otherwise a write-in is valid based only on the bubble. Write-in areas that cross the write-in area threshold set in the system settings will be shown in the write-in adjudication flow in VxAdmin. The system's default write-in area threshold is 5%.

    Identifying contest options
    Scoring write-in areas

    After all bubbles and write-in areas are scored, interpretation is complete and the images are saved to disk. The votes are inferred from the bubbles based on the mark thresholds and eventually exported to cast vote records.

    If interpretation didn't work, one possibility is that the ballot is actually a machine marked ballot, so the interpreter will then attempt to interpret the ballot as a machine marked ballot. Since votes are encoded into the QR code, the interpreter only has to find the QR code. It searches the entire document for a QR code. By searching the top and bottom half separately, it can infer the orientation of the ballot because machine marked ballots have QR codes in the top right.

    hand marked ballot
    Otsu's methodarrow-up-right
    Vertical streak detected
    No vertical streak detected
    circle-info

    User Manual Reference:

    hashtag
    Ballot Mode

    After initial configuration, VxCentralScan is in test ballot mode. The election manager can toggle between test ballot mode and official ballot mode. In official ballot mode, only official ballots can be scanned and exported CVRs will be official ballot CVRs. In test ballot mode, only test ballots can be scanned and exported CVRs will be test ballot CVRs. If allowOfficialBallotsInTestMode is set in the system settings, official ballots will be allowed in test mode but exported CVRs will still be test CVRs.

    Switching between ballot modes clears all scanned ballot data. The election manager can switch from test ballot mode to official ballot mode at any time. When in official ballot mode after ballots have been scanned, the election manager can only switch back to test ballot mode if the scanned ballot data has been backed up.

    hashtag
    Unconfiguring

    VxCentralScan can be unconfigured by an election manager or system administrator. If ballots have been scanned in official ballot mode, an election manager can only unconfigure the machine after scanned ballot data has been backed up. System administrators can unconfigure the machine at any time.

    hashtag
    Batch Scanning

    hashtag
    Scanner Management

    VxCentralScan is compatible with the Ricoh fi-8170 and Ricoh fi-7600 production scanners. Once either scanner is detected, the user may begin scanning batches. The scanners are controlled via commands provided by the Debian sane package ("Scanner Access Now Easy") which creates a uniform API for most commercial scanners. As a result, no scanner-specific drivers are required.

    hashtag
    Batch Management

    When the user triggers a batch scan, the scanner will start a batch and begin scanning sheets one a time. The scanner will pull the paper through and transfer a scanned image to the application which will then interpret the ballot according to the current election definition. If any issues are found with the ballot - either the ballot is incompatible or the marks trigger some adjudication reason - scanning will pause and the election manager will be prompted to remove or tabulate the ballot. When pausing for adjudication, the batch is not yet ended. Once the election manager addresses the ballot, scanning will continue until there are no more ballots in the hopper to be scanned. At that point, the batch will end.

    The start time, end time, size, and index of all batches is tracked and displayed to the election manager. If a mistake was made in organizing batches or adjudicating a ballot, election managers can delete any individual batch or delete all batches.

    circle-info

    User Manual Reference:

    hashtag
    Imprinting

    Both Ricoh scanners can be used with an optional imprinter - the fi-819PRB for the fi-8170 and the fi-760PRB for the fi-7600. As the ballot exits the scanner, the imprinter prints an identifier on the side margin of the ballot. The identifier is the batch's UUID suffixed with the index of the sheet in the batch e.g. 378f6a69-62d3-4184-a1a7-3a5d90083e21_0000 for the first sheet in a batch. The identifier will appear in the CVR as the BallotAuditId. Imprinting allows later reconciling CVRs to ballots such as in ballot comparison audits.

    hashtag
    Batch UUIDs

    The v4 UUID (universally unique identifier) for each batch is generated when the batch is first created. It is generated with the node package uuid which uses the system's underlying FIPS-complaint OpenSSL implementation to generated random bytes.

    hashtag
    Ballot Issues & Adjudication

    Batch scanning pauses whenever a ballot is not counted for any reason. Sometimes the ballot was not interpreted or cannot be accepted, in which case the ballot must be removed:

    • Vertical Streaks Detected - the scanner may require cleaning

    • Wrong Ballot Mode - test ballots in official ballot mode or official ballots in test ballot mode

    • Wrong Election - the hash on the ballot does not match the currently configured election

    • Unreadable - the ballot image could not be successfully interpreted, possibly because it is not a valid ballot or because the image skew was too great

    In other cases, the ballot requires adjudication. The adjudication reasons for VxCentralScan are set in the system settings as centralScanAdjudicationReasons and map to the following:

    • Overvote - at least one contest is overvoted

    • Undervote - at least one contest is undervoted

    • Blank - all contests are blank

    In these cases, the affected contests will be highlighted on screen to the election manager and they will have the option to remove or tabulate the ballot.

    circle-info

    User Manual Reference:

    hashtag
    Exporting CVRs

    CVRs must be exported onto a USB drive and taken to VxAdmin for aggregation and reporting. After ballots are interpreted, their images are saved to disk and their interpretation is stored in VxCentralScan's data store. On export, all CVRs are pulled from the data store, converted to the CVR CDF, and written to the USB drive.

    circle-info

    User Manual Reference:

    Election Package

    All screens surpass the 10:1 minimum contrast ratio under 500 lux (8.1-A.1.b)

  • All screens surpass the 12" minimum diagonal display size specified in 8.1-A.2.a, which itself surpasses the 7.9" minimum diagonal display size specified in 8.1-A.3a.

  • All screens surpass the 1920 x 1080 minimum display resolution specified in 8.1-A.2b, which itself surpasses the 1024 x 768 minimum display resolution specified in 8.1-A.3.b.

  • Device
    Display Diagonal
    Resolution
    Contrast
    Max. Brightness

    VxScan

    15.6"

    1920 x 1080

    1,000:1

    310 nits

    VxMarkScan

    15.6"

    1080 x 1920

    700:1

    220 nits

    hashtag
    Eliminating Hazards

    All audio and video devices are tested to be in accordance with the requirements of IEC/UL 62368-1 (8.1-K).

    Device
    Test Report

    VxScan

    VxMarkScan

    Report Available on Request

    Central Laptops

    hashtag
    Audio-Visual Settings

    The audio-visual settings for the voter experience are described in the System Overview:

    • VxMarkScan Function

    • VxScan Function

    this open-source scriptarrow-up-right
    Cast Vote Records
    this open-source scriptarrow-up-right
    Ballot QR Code Data Format
    https://vx-hmpb-qr-decoder.pages.devarrow-up-right
    Passed
    Failed

    CSV Exports

    Both tally reports and ballot count reports can be exported in comma-separated values (CSV) format.

    hashtag
    Tally Report CSV Structure

    In the CSV tally report, the vote total for each candidate or contest option is listed in a single row. In addition, there are rows for overvote and undervote totals for a contest.

    For example, here is an excerpt of a tally report including the results for one contest:

    Formatted version of the above CSV excerpt

    The "Precinct" and "Precinct ID" columns are that are included because this example export groups results by precinct. The other fields are standard fields:

    Header
    Values

    If manual results were entered, two additional columns will be added - "Scanned Votes" and "Manual Votes." These columns denote which votes for each selection came from the scanners vs manual entry.

    The results of write-in adjudication are always included in the CSV exports. All write-in candidates will appear with their adjudicated name and a UUID assigned by VxAdmin. Unadjudicated write-in candidates will appear as "Unadjudicated Write-In" with the ID "write-in". Unlike in the printed reports, write-in candidates are never consolidated.

    hashtag
    Ballot Count Report CSV Structure

    The ballot count report CSV is the same as the table presented in the . For example:

    The "Precinct", "Precinct ID" and "Voting Method" columns are that are included because this example export groups results by precinct and voting method. The "Total" field is a standard field on all ballot count CSV exports, but other ballot or sheet count fields may appear depending on the election and loaded results:

    Header
    Values

    hashtag
    Shared Metadata Structure

    Any filters or groupings which apply to each row will be indicated in the row itself by metadata columns. For example, in the example export above, the "Precinct" column lists which precinct group each row represents.

    If a row is filtered by a single attribute value (e.g. represents one precinct rather than multiple precincts) then the following basic metadata fields are used:

    Header
    Value

    If a row is filtered by multiple attribute values, the following columns may be used:

    Header
    Value

    In cases as above, where a row value includes comma-separated values, those values will be wrapped in quotation marks per typical CSV formatting in order to allow consumers to properly differentiate columns.

    Procedural and Operational Security

    VxSuite can be operated securely using the following these procedures. Some of these procedures are intentionally redundant for defense-in-depth as it is always expected that some operational mistakes are made.

    hashtag
    Using Proper Equipment

    VxSuite should be used only with sanctioned equipment and peripherals. In particular, when connecting USB devices to any VxSuite component, use only USB devices of the type specified in this documentation, and only devices of known and reputable source.

    hashtag
    In Between Elections

    When there are no active elections happening, VxSuite equipment should be physically secured so it is difficult to access and so that any access is evident at a later date.

    • VxAdmin laptop and peripherals should be kept in their case, with numbered seals through both case seal points, preventing the case from being opened without breaking one or both seals.

    • VxCentralScan laptop and peripherals should be kept in their case, with numbered seals through both case seal points, preventing the case from being opened without breaking one or both seals.

    • The small Fujitsu/Ricoh scanner that works with VxCentralScan should be kept in its supplied soft case, with a numbered seal through the appropriate zipper hole, preventing the case from being opened without breaking the seal.

    You may consider occasionally resetting the PIN on the system administrator cards. This can be done using the VxAdmin laptop.

    hashtag
    During L&A Testing

    Both VxAdmin and VxScan are required for Logic & Accuracy testing. VxCentralScan is required if it is planned to be used for counting absentee ballots. VotingWorks's recommended practices take into account that this testing is often performed in view of the public.

    • When retrieving all components from their locked storage location, ensure that the seal numbers match the logs.

    • Keep clear and strong custody of all smart cards.

    • Use the system admin card only long enough to un-configure VxAdmin, VxScan, and VxCentralScan from the last election, and to program VxAdmin for the new election. Then return the system admin card to its secure storage.

    At the end of L&A testing, ensure that the VxScan is ready and secured for election day:

    • the correct USB drive is inserted into one of the two USB slots.

    • the system has been switched to official-ballot mode.

    • the VxScan is powered down.

    If using VxCentralScan, ensure that that:

    • it is switched to live mode

    • it is shut down and put away in its case

    • the case is closed and sealed.

    Store all L&A'ed equipment, with recorded seal numbers, in a secure location until election day.

    hashtag
    During an Election

    Ensure that seals on equipment are untouched and appropriately numbered since L&A.

    hashtag
    Opening The Polls

    After setting up VxScan on the ballot box and opening the polls, ensure that:

    • the ballot box is locked and/or sealed

    • the auxiliary ballot box is locked and/or sealed

    • the VxScan is attached to the ballot box using the locking mechanism

    All seal numbers should be recorded.

    hashtag
    During Vote Casting

    A poll worker should observe VxScan from afar at all times, ensuring voters are not attempting to break any seals.

    If a ballot jam requires opening the poll worker door or the ballot box door, record the corresponding seal number before breaking, and ensure resealing afterwards, recording the new seal number(s).

    hashtag
    Scanning Absentee Ballots

    VxCentralScan is only meant to be accessed by authorized election administrators. However, it is safe to project the screen via overhead projector, as long as the smart card PIN is entered via the keyboard, and not via the mouse.

    hashtag
    Closing the Polls

    Unsealing the poll worker door is required to extract the USB drive after polls are closed. Ensure the seal number matches the expected value. Once the polls are closed and the USB drive is removed, take care to secure the chain of custody of the USB drive. VxScan should be closed up and sealed.

    hashtag
    After an Election

    Pack up all components in their respective cases and apply seals. Record those seals.

    Additionally, any auditing or review of audit logs should be completed immediately after exporting those logs from the VxScan or Central system to a USB. If there is a concern about a break in the administrative chain of custody, the user should re-export the logs to a USB from the machine and can compare the original export with the re-export to determine the logs have not been tampered with while on the USB. The logs maintained on the system are unalterable and should be pulled and reviewed in one process to ensure that chain of custody is maintained.

    Warranty Model

    hashtag
    Estimated Replacement Rates

    VxScan (incl ballot box)

    VxAdmin

    VxCentralScan

    VxMarkScan

    Estimated Replacement Rate

    10 years

    *Costs quoted here reflect 2024 costs. VotingWorks expects prices to increase over time, in line with US inflation rates.

    hashtag
    Estimated Warranty Types and Costs

    VotingWorks requires all voting equipment customers to purchase our Technology Repair, Upgrade, Support and Training (“Trust”) Services. TRUST Services will cover warranty for all products purchased. Average annual cost of TRUST Services will not exceed 5% of the equipment purchase price for years 1-10.

    hashtag
    Associated Replacement Policies, Services, and Available Maintenance Agreements

    A sample TRUST Services Agreement is available .

    hashtag
    Plans for Collecting, Maintaining, and Reporting Data to the EAC to Support and Validate Estimates

    VotingWorks will continually collect data on warranty usage at the product level and compile such data into reports. VotingWorks will share this data with the EAC at least every two years.

    Physical Security

    In addition to the processes in Procedural and Operational Security, VxSuite employs the following physical security controls for each component.

    hashtag
    VxAdmin

    • VxAdmin laptops are stored and transported in a case with two tamper-evident seal points to detect any unauthorized physical access.

    • VxAdmin laptops have a tamper evident adhesive seal on the laptop itself to detect any unauthorized physical access to the laptop internals.

    • VxAdmin laptops BIOS configurations do not allow the machine to boot if the laptop itself is opened without entering a vendor-only password & returning the device to VotingWorks.

    • VxAdmin has no exposed ports that are not used for voting system operations. VxAdmin's printer has an ethernet port blocker installed.

    hashtag
    VxCentralScan

    • VxCentralScan laptops are stored and transported in a case with two tamper-evident seal points to detect any unauthorized physical access.

    • VxCentralScan laptops have a tamper evident adhesive seal on the laptop itself to detect any unauthorized physical access to the laptop internals.

    • VxCentralScan laptops BIOS configurations do not allow the machine to boot if the laptop itself is opened without entering a vendor-only password & returning the device to VotingWorks.

    hashtag
    VxScan

    • VxScan has two external tamper-evident seal points to detect any unauthorized physical access.

    • VxScan has three interior adhesive tamper-evident seals (1 on top panel; 2 on bottom panel) to detect any unauthorized access to the device internals.

    • VxScan has a tamper-evident seal point at the intersection of the poll worker door and security bolt to ensure secure ballot box attachment and detect any unauthorized access to poll worker functions.

    hashtag
    VxMarkScan

    • VxMarkScan transport & storage cases have tamper-evident seal points to detect any unauthorized physical access.

    • VxMarkScan has an adhesive tamper-evident seal behind the touchscreen to detect any unauthorized physical access to the device internals.

    • VxMarkScan ballot box has a tamper-evident seal point to detect any unauthorized access to cast ballots and the printer-scanner.

    Quality Assurance Manual

    VxSuite product quality is ensured through both focused processes on individual aspects of the system and through overall integration testing that ensure the system is working well end-to-end.

    hashtag
    Quality Assurance Protocols – Software

    hashtag

    VxMarkScan Hardware

    hashtag
    Overview

    VxMarkScan exposes various hardware interfaces for various modes of voting. The touchscreen displays the ballot and allows making selections with touch. It tilts forward and backwards for easier viewing and for storage. An accessible controller sits on the left side of the screen held in place with light magnetic force. Beneath the accessible controller is the headphone input and above the accessible controller is a recess for resting headphones. On the lower right corner, there is another input jack for a PAT (Personal Assistive Technology) device such as a sip-and-puff.

    The right side of the machine is the paper path. Paper is inserted into the printer-scanner by feeding it forward on the front paper input. When the ballot is cast, it is ejected to the rear into the attached ballot box. In case of paper jams, the printer-scanner cover can lift to expose the printer-scanner. If the cover is opened while polls are opened without authentication, an alarm will be triggered through the onboard speaker.

    Hashing of Continuously Exported Cast Vote Records

    hashtag
    Continuous Export

    Our precinct scanners export cast vote records (CVRs) to USB drive continuously, as ballots are cast. Continuous export also allows for a speedy polls close, as cast vote records need not be exported all at once on polls close.

    hashtag

    message = 1//shv1//<system-hash>#<software-version>#<election-id>#<current-timestamp>
    qrCode  = <message>;signature(<message>);<machine-cert>
    Precinct,Precinct ID,Contest,Contest ID,Selection,Selection ID,Total Votes
    West Lincoln,20,Mayor,mayor,Sherlock Holmes,sherlock-holmes,0
    West Lincoln,20,Mayor,mayor,Thomas Edison,thomas-edison,0
    West Lincoln,20,Mayor,mayor,Write-In,write-in,0
    West Lincoln,20,Mayor,mayor,Overvotes,overvotes,0
    West Lincoln,20,Mayor,mayor,Undervotes,undervotes,0

    The larger Fujitsu/Ricoh scanner that works with VxCentralScan should be kept in its supplied manufacturer box, with tamper evident tape along all sides and a numbered sticker seal on the main opening.

  • VxScan should be kept closed with a numbered seal through one of the two seal points, preventing the case from being opened without breaking the seal.

  • VxAdmin, VxCentralScan, VxScan, and the Fujitsu/Ricoh scanner, once sealed, should be kept in a safely locked room or storage area that only authorized election administrators have access to.

  • The system admin smart cards should be kept in a safe or locked drawer, separately from VxAdmin. The PIN for the system admin smart card, if recorded on paper, should also be kept locked separate from both VxAdmin and the card.

  • the VxScan case is closed and sealed.
    the poll-worker access door on the VxScan is sealed shut

    VxCentralScan has no exposed ports that are not used for voting system operations. VxCentralScan's attached batch-scanner (fi-8170) has an ethernet port blocker installed.

    VxScan's ballot box has a seal point for each ballot storage area (main & auxiliary compartments) to detect any unauthorized access to cast ballots.

  • VxScan triggers a visual & audible alert when a USB drive is removed in an activated state to alert any unauthorized access.

  • VxScan has no exposed ports when the poll worker door is sealed.

  • VxMarkScan triggers a visual & audible alert when the printer-scanner and/or printer-scanner cover is opened in an activated state to alert any unauthorized access.
  • VxMarkScan has no exposed ports when the ballot box is attached and sealed. An ethernet port blocker is also installed on the ethernet port accessible when the ballot box is detached.

  • Automated Unit Tests

    VotingWorks code has extensive unit test coverage. All libraries in the vxsuite repositoryarrow-up-right have near 100% coverage, meaning that almost every single line of code runs whenever testing is run. Across all libraries, there are over 3,000 unit tests which all together include over 10,000 assertions about the software's behavior.

    Each test always either passes or fails. A test fails if an error is thrown or an assertion fails. An assertion may be something like "the phrase General Election appear on screen" or "there are 56 votes for a specific candidate after loading cast vote records."

    Whenever changes are made to VotingWorks code, all tests are automatically run as part of a continuous integration (CI) process through CircleCI. Code changes cannot be merged unless all tests pass. A single failing test will prevent changes from being merged. Every test run on CirceCI provides evidence that the software is operating as expected.

    Test runs are public information available via CircleCI. For example, tests running in vxsuite are tracked herearrow-up-right.

    If tests are flaky, meaning that they usually pass but occasionally don't, VotingWorks investigates and fixes the underlying issue. Flaky tests are automatically reported by the CircleCI tooling. VotingWorks reviews new flaky tests on a weekly basis.

    hashtag
    Automated End-to-End Tests

    In addition to unit tests, VotingWorks code has end-to-end integration tests for all applications. These operate in the same continuous integration framework as the unit tests, but ensure the system works at higher-level. Instead of simply running the application server or the frontend, the entire stack is simulated to ensure that the components of the system - data store, user interface, communication between processes - are working as expected. Like unit tests, these tests are run before any code change is merged.

    hashtag
    Regression Testing

    Whenever a software issue is discovered in manual testing or in actual operation in the field, VotingWorks creates an automated regression test after fixing the issue. For example if a particular ballot image was not interpreted but should have been interpreted, that ballot image would be used to create an automated regression test to ensure that not only is the issue fixed but that future changes cannot recreate the issue.

    Even tests which are not explicitly created as regression tests have an anti-regression function. The advantage of having a robust test suite is that failing tests will inform developers when new fixes or improvements break previous functionality.

    hashtag
    Manual Testing

    While we strive to cover as much as we possibly can with automated tests, there remains significant value in rigorous manual testing of software on actual hardware. We periodically conduct such passes and perform particularly rigorous passes before freezing software for a release.

    To organize this process, we make use of checklists. A base set of checklists can be viewed here: Software QA Checklistsarrow-up-right. When performing QA before a release for a particular state or election, we often tweak these base checklists to hone in on the specific circumstances, e.g., using specific adjudication settings and paper ballot lengths.

    hashtag
    Safe Concurrency (2.5-B)

    VxSuite practices safe concurrency by using programming languages that, in their design, avoid the most common dangers of concurrency.

    Most of the application code, both frontend and backend, is written in TypeScript which compiles to JavaScript executing at runtime. JavaScript is a single-threaded language. While code can execute asynchronously, it cannot execute simultaneously with other code, preventing most instances of unsafe concurrency. We do sometimes make use of a mutex, and our TypeScript mutex implementation is well-testedarrow-up-right.

    Performance-critical parts of the application, like image processing for ballot interpretation, are written in Rustarrow-up-right. Rust was designed specifically to be a memory-safe language alternative to common low-level alternatives like C. It requires that every piece of memory has a single owner responsible for the memory's lifecycle. Unsafe memory operations are prevented by the tooling itself - the compiler and linter - to ensure memory-safe programs. The language is recommended for security critical operations by the White House (2024 Reportarrow-up-right) and industry leaders. While memory safety and concurrency safety are slightly different things, the two are deeply intertwined, and a memory-safe language avoids most of the pitfalls of unsafe concurrency.

    Despite those protections, unsafe concurrency is technically still possible, as it is widely acknowledged as impossible to definitively prove that a complex piece of software is free of race conditions.

    In order to catch any other instances of unsafe concurrency, VotingWorks tests software operation at scale in automated tests, as discussed above. In actively developed repositories like those for VxSuite, tests are running hundreds or thousands of times before the software is actually used on a machine. At that scale, intermittent concurrency issues are surfaced in the form of flaky tests. VotingWorks reviews flaky tests weekly and uses them to identify and fix any concurrency issues.

    Once software is actually imaged to hardware, VotingWorks tests the software thoroughly and at high volumes. For example on VxScan, the precinctScanEnableShoeshineMode flag in the system settings allows testing the scanner with a repeated scan that is run thousands of times before a release. In addition, VotingWorks attempts to identify edge cases and break the software during testing by performing operations in unusual or rapid succession which may reveal concurrency issues.

    hashtag
    Quality Assurance Protocols – Hardware

    hashtag
    Hardware Design

    VotingWorks uses large-scale COTS hardware wherever possible, including laptops, single-board computers, document scanners, and printers. By virtue of designing around components that are produced and field-tested at much higher scale than voting machines ever can be, we reduce the chance of a quality problem at the design phase.

    For components that must be custom-made, for example the VxScan precinct scanner module and the ballot box, we have followed the industry-standard multi-phase design process to ensure that quality issues are caught early, long before we've committed to large production runs. In particular:

    • design prototyping – every individual hardware component is prototyped using 3D-printing and laser-cut parts in order to validate CAD designs, in particular when managing a paper path.

    • lab prototypes – every hardware subsystem – e.g. the VxScan module or the VxBox ballot box – goes through multiple lab prototypes of increasing fidelity. Each prototype is fully functional and is tested with thousands of ballots, through setup and teardown repeatedly. Weaknesses are cataloged and fed into the next lab prototype.

    • engineering prototype – once the lab prototype is fully validated, an engineering prototype is designed, tweaked for manufacturing (DFM). The tooling is then built, in order to produce an engineering prototype that is as close as possible to the final product. The tooling is adjusted in minor ways based on tests performed on the engineering prototype.

    By the time a VotingWorks hardware subsystem goes to assembly-line production, it has gone through a number of iterations to ensure that the design is high quality.

    hashtag
    Component Testing & Validation

    VotingWorks works closely with suppliers to ensure quality components. We require suppliers to provide documentation of their QA procedures (TA2.1.1-A.2 1). VotingWorks's policy is to report all defective components to the supplier in order to jointly plan mitigations for future orders.

    VotingWorks component test procedures vary on a component-by-component basis:

    • Custom Manufactured Parts - Metal and plastic parts manufactured specifically for VotingWorks (e.g. a metal panel in VxScan) are visually inspected and measured against dimensions specified in their engineering drawings.

    • Complex Electrical Subassemblies - Large electrical components, which are often critical components, are tested before being installed in any machine. For example, the embedded scanner in VxScan is tested for motor control and image quality. VotingWorks has command-line interfaces that allow controlling and testing devices outside of a full software installing, simply by connecting them to a development machine.

    Smaller or common COTS components, like a simple USB cable or piece of hardware, are visually inspected and their proper operation is covered by the quality assurance done on each individual unit.

    hashtag
    Assembly (Protocol & Detailed Instructions)

    Our complete assembly work plans are available in the document repositoryarrow-up-right.

    hashtag
    Quality Assurance Protocols – Integration Testing

    hashtag
    Full System Integration Testing

    Many issues only emerge when software is installed on production hardware or when the various components of the system are used together. In order to catch these higher-level system issues, VotingWorks performs full system integration testing before every release.

    At VotingWorks locations, VotingWorks testing staff set up the full suite of hardware with the latest software release. The testing procedures are designed to imitate an election flow and test any common corner cases or past issues. Most testing procedures are repeated with multiple election packages and system settings to confirm that there are not issues specific to certain configurations.

    When an issues is found, the issue is immediately escalated to the engineering team for a fix. A new release is created and testing procedures are restarted in full to ensure fixes do not introduce regressions.

    We have comprehensive test reports:

    • external testing reportsarrow-up-right

    • internal testing reportsarrow-up-right

    hashtag
    Production Unit Quality Assurance

    Every unit assembled in production is manually tested against a comprehensive checklist to ensure the unit is fully operational. The quality assurance procedures are designed to imitate an election flow and check for any issues found on past units. Checklists for VxAdmin, VxMarkScan, VxScan, and VxCentralScan are public here in the documentation repositoryarrow-up-right.

    10 years

    10 years

    10 years

    Estimated Cost Per Replacement

    $7,500*

    $2,500*

    $2,500*

    $7,500*

    herearrow-up-right

    Central Laptops

    14"

    1920 x 1200

    1,330:1

    300 nits

    UL 62368-1 Test Reportarrow-up-right
    UL 62368-1 certifiedarrow-up-right
    Ballot Config Encoding

    The serial number of the scanner. Included by default if the batch is included.

    Batch

    The label of the scanned batch

    Batch ID

    The scanner-assigned UUID of the scanned batch

    Contest

    The title of the contest

    Contest ID

    The internal identifier of the contest in the election definition

    Selection

    The candidate name for candidate contests, the option label for yes-no contests, or "Overvotes" or "Undervotes"

    Selection ID

    The internal identifier of the contest option, or "overvotes" or "undervotes"

    Total Votes

    The vote count for the selection

    Manual

    The ballot count of manually entered results.

    Scanned

    The count of all ballots loaded as cast vote records. The field appears if there are manual ballots or if the election is multi-sheet. In a multi-sheet election, this is the count of the first sheet.

    Scanned Sheet {N}

    The count of a subsequent ballot sheet. The count of the second sheet of all ballots would be "Scanned Sheet 2".

    Total

    The total ballot count.

    Precinct

    The name of the precinct

    Precinct ID

    The identifier of the precinct from the election definition

    Party

    The short name of the party e.g. "Republican". Included by default if the ballot style is included, in a primary.

    Party ID

    The identifier of the party from the election definition

    Ballot Style ID

    The identifier of the ballot style

    Voting Method

    "Absentee", "Precinct", or "Provisional"

    Included Precincts

    The precinct identifiers separated by commas

    Included Parties

    The party identifiers separated by commas

    Included Ballot Styles

    The ballot style identifiers separated by commas

    Included Voting Methods

    The voting method labels ("Precinct", "Absentee", or "Provisional") separated by commas

    Included Scanners

    The scanner serial numbers separated by commas

    Included Batches

    The batch identifiers separated by commas

    metadata fields
    printed ballot count reports
    metadata fields
    Formatted version of the above CSV excerpt

    Scanner ID

    Precinct,Precinct ID,Voting Method,Total
    West Lincoln,20,Precinct,0
    West Lincoln,20,Absentee,0
    East Lincoln,21,Precinct,0
    East Lincoln,21,Absentee,0
    South Lincoln,22,Precinct,0
    South Lincoln,22,Absentee,0
    North Lincoln,23,Precinct,0
    North Lincoln,23,Absentee,0

    The primary modification made by VotingWorks to the original Smartmatic hardware is adding a smart card reader for authentication. The smart card reader is positioned beneath the accessible controller:

    Smart card insert

    Power is controlled by a button in the back left of the machine. When activated, an LED will illuminate the power button. Between the power button and the power port is an additional headphone input which is not used by VxMarkScan.

    Power controls

    VxMarkScan does not require any direct bodily contact or for the body to be part of any electrical circuit to function.

    hashtag
    Storage

    VxMarkScan is shipped and stored in large hardshell cases with custom foam cutouts. The first case, accented in blue, is for the BMD itself, its headphones, and its power supply. The second case, accented in yellow, is for the other peripherals - legs, power supply holder, privacy shield, and ballot box.

    The BMD itself must be padded as shown below for transport and vibrational testing. Padding is used to protect the screen and hold it in place, to hold the accessible controller in place, to hold the printer-scanner cover in place, and to further secure the BMD within the enclosure.

    BMD case fully packed and padded
    Peripherals case fully packed
    Peripherals case with privacy shield removed
    Peripherals unpacked

    hashtag
    Assembly

    Assembly instructions are covered in the user manual under . In short, the legs are unfolded and the power block holder is set on the legs with the power block inside. The BMD then fits onto the legs with grooves on its underside.

    hashtag
    COTS Components

    The vast majority of the VxMarkScan hardware is the VSAP (Voting Solutions for All People) arrow-up-rightBallot Marking Device (Model 150) developed by Los Angeles County, manufactured by Smartmatic, and purchased through Los Angeles County. In addition, VotingWorks includes a few peripherals or COTS components added through modification. Documentation for these components can be found in the documentation repositoryarrow-up-right or in the separately provided Los Angeles County documentation.

    Manufacturer
    Component
    Mfr. Part Number
    Criticality

    Smartmatic

    Ballot Marking Device

    VSAP-150

    High

    GoldenMate

    Uninterruptible Power Supply

    UPS 1000VA/600W

    Low

    HID

    Smart Card Reader

    R31210375-1

    The specified neckloop achieves a T4 rating when used with assistive hearing devices that include T4 rated telecoils.

    hashtag
    Criticality Discussion

    The VSAP system provided by LA County is the primary component and the highest criticality component. The entire system runs on it. The embedded computer and the printer-scanner are both responsible for the printing of ballots and the interpretation of ballots. The various interaction interfaces - touchscreen, accessible controller, and PAT input - can all affect voter selections. VotingWorks and Los Angeles County have a robust partnership that includes the sale of the hardware itself, documentation transfer, and alignment on access control and quality assurance procedures.

    The only other critical component, with medium criticality, is the HID smart card reader. As it is responsible for communicating with smart cards and facilitating authentication, it is a sensitive component.

    Accessible Controller
    Merkle Tree Structure

    To perform continuous export while also keeping signatures, i.e., authenticity information, up-to-date, we have to be able to write both CVRs and authenticity information incrementally. (It isn’t enough to just hash and sign new data. We need an up-to-date root hash/signature.) We can use a Merkle treearrow-up-right structure to accomplish this efficiently.

    Assuming every CVR has a random UUID, e.g. 4d6a9dad-e6d6-4a29-89bc-9ab915012b73, we can specifically use the following structure:

    hashtag
    In Practice

    We don’t actually have to 1) use a nested directory structure on the USB or 2) store all intermediate hashes on the USB. We can store the structure and intermediate hashes on the machine in a database table, e.g.

    CVR ID Prefix 1
    CVR ID Prefix 2
    CVR ID
    Hash

    -

    -

    -

    Root hash

    4

    -

    -

    4 hash

    4

    Then on the USB, we can use a flat structure that’s much easier to reason about and iterate over:

    The database table makes recomputing hashes easy, as retrieval of all hashes for a given ID prefix becomes a simple SQL query. This approach also decreases the chance that we accidentally depend on data written to the USB drive when computing hashes, protecting against compromised or faulty USB drivesarrow-up-right.

    In the above examples, we’ve listed a root-hash.txt file and have signed that. In practice, we use a JSON file capable of storing other metadata and sign that:

    Sample metadata.json:

    hashtag
    Import

    Whenever a machine imports a CVR directory, it authenticates the CVRs by 1) verifying the signature on the metadata.json file and 2) recomputing the “castVoteRecordRootHash” in metadata.json from scratch to ensure that it’s correct.

    hashtag
    Code Links

    Refer to the following code links for more details:

    • https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/cast_vote_record_hashes.tsarrow-up-right — CVR hashing logic, including the Merkle tree implementation

    Ballot QR Code Data Format

    Both hand-marked paper ballots and machine-marked ballots contain QR codes. For hand-marked paper ballots, the QR code contains only metadata about the ballot. For machine-marked ballots, the QR code contains both metadata and voter choices.

    In order to make the information as compact as possible, information is coded as binary values that reference the election definition. For example, instead of encoding the precinct name (e.g. "Fire Station Precinct") the QR code contains the index of the precinct within the election definition. If the precinct were the first precinct listed in the election definition, the value would be 0. If it were the second precinct listed in the election definition, the value would be 1. The binary sequence is ultimately encoded into the QR code as Base64 for broad compatibility with devices that scan QR codes.

    hashtag
    Decoding QR Codes Manually

    Take following steps to decode a barcode manually and, in the case of a machine-marked ballot, manually verify the encoded selections are correct:

    1. Scan the QR code with a smartphone camera or barcode reader. If your smartphone does not automatically detect a value, you may use any freely available QR code scanning app.

    2. Copy and paste the scanned value into any Base64 to binary converter.

    3. Inspect the binary values and compare them to the encodings described below. In order to make sense of the values, you will need the associated available for comparison.

    You may use this process to verify that the encoded information in the ballot QR code matches the information presented on the ballot to human readers.

    An easier, recommended approach is to simply scan the ballot(s) at VxScan or VxCentralScan. You can confirm the interpretation (and therefore in most cases, the QR code) is correct by looking at a results report. You can also inspect the exported from the scanner, which contain the images and interpretation for each ballot, to confirm that the metadata and voter selections were encoded and decoded correctly, similar to an .

    hashtag
    HMPB QR Code Data Format

    Component
    Length
    Description

    hashtag
    Ballot Config Encoding

    Component
    Length
    Description

    hashtag
    BMD QR Code Data Format

    Unlike the HMPB QR code, the BMD QR code actually encodes votes.

    Component
    Length
    Description

    hashtag
    Write-In Encoding

    If the contest does not allow write-ins (allowWriteIns = false) then the candidate contest data ends after the bits for the list of candidates. If the contest does allow write-ins (allowWriteIns = true), then write-in data will follow the candidate roll call and start with the number of write-ins. The maximum number of write-ins is the difference between the number of possible votes in the contest (e.g. is it a vote for one or vote for three contest) and the number of votes used on non-write-in candidates. The number of write-ins is written with the number of bits that would be required to write the maximum number of write-ins. For example, if a contest is "Vote for Five" and the ballot already contains two votes, the maximum number of votes is three. Three takes 2 bits to represent, so the number of write-ins will be 11, 10, 01 , or 00 for 3, 2, 1, or 0 respectively.

    After the number of write-ins, the write-ins are written in series, with 6 bits containing the length of the write-in, in bytes, and then the write-in itself in however many bytes after that. The bytes are in UTF-8 format.

    hashtag
    QR Code Specifications

    HMPB and BMD QR codes are with .

    hashtag
    Source Code

    The source code and further technical documentation of how ballot QR codes are encoded and decoded can be found in the .

    Vulnerability Management

    hashtag
    Vulnerability Disclosure Policy

    VotingWorks' vulnerability disclosure policy is publicly available here: https://github.com/votingworks/vxsuite/security/policyarrow-up-right

    The public disclosure policy provides instructions on how to report a vulnerability, where to see known vulnerabilities, and the coordinated vulnerability disclosure process VotingWorks follows.

    hashtag
    Patch Management Plan

    We handle vulnerabilities using the following coordinated vulnerability disclosure process:

    • The reporter reports the vulnerability privately to VotingWorks.

    • VotingWorks works privately with the reporter to understand the vulnerability, with an initial response within 10 business days of receipt of the report.

    • VotingWorks prepares fixes as needed for reported vulnerabilities. Some fixes will be operational, others in software, and others potentially in hardware. Where the issues affect a third-party component, VotingWorks will do its best to coordinate advisories and disclosures with other involved parties.

    hashtag
    Known Vulnerabilities Not of Concern

    Given the protection mechanisms we use to prevent unauthorized software from running on VxSuite components, the simplest way to perform a vulnerability scan is to use Nessus in a host operating system, with VxSuite components running as guest virtual machines (VMs). We turn off our networking blocks on those VMs for the sake of performing a useful vulnerability scan.

    On each of these components, the same vulnerabilities are found by Nessus. There are 15, and they are all in the "Info" category of vulnerability, meaning that they only allow for information gathering about the host, not for any corruption or direct attack. All of these issues are listed here, with an explanation as to why they are not vulnerabilities of concern.

    Vuln #
    Description
    Explanation/Mitigation

    Hardware Criticality and Supplier Analysis

    hashtag
    Criticality Criteria

    hashtag
    Overview

    VxSuite hardware contains numerous subcomponents, some of which are subassemblies containing hundreds of subcomponents themselves. Successfully building, deploying, and maintaining VxSuite requires that components be sourced from scores of suppliers. If any component cannot be procured, it could impact the ability to build the system at all. If any component is defective or compromised, it could degrade the system's performance. In that sense, every component in a voting system is critical. Certain components are more critical than others, however, and the following analysis defines our strategy for ranking components with high, medium, or low criticality.

    The two primary criteria we consider when assessing criticality are ability to find alternative suppliers and relationship to sensitive election data. If we are unable to easily find alternative suppliers, the component is at least medium criticality. If the component processes sensitive election data, the component is at least medium criticality. If both are true or one is especially true, the component is high criticality. In addition, there are a number of other lesser criteria mentioned below.

    hashtag
    Relationship to Sensitive Election Data

    Any component that processes election data is at least medium criticality because, if it fails or is compromised by a malicious actor, it could theoretically alter configuration, operation, tabulation, or aggregation which could compromise the interpretation of ballots, the tallying of votes, or voter privacy.

    Example 1: Any scanner in the system, because it is responsible for recording ballot images, is a high criticality component. Defects in the scanner could produce unreliable ballot images. Sophisticated malicious attacks could alter firmware or intercept data transmission to produce altered images.

    Example 2: USB cables transfer election data between components and are always at least medium criticality. USB cables are generally simple and substitutable, but highly sophisticated attacks involving manipulating data passing through a USB cable are possible.

    Example 3: Power cables don't carry data to and from devices so, even though they are obviously critical to the operation of the device, they don't have a direct relationship to sensitive election data and are not more critical as a result.

    hashtag
    Ability to Find Alternative Suppliers

    Most components can be or already are manufactured by multiple manufacturers. Standard screws can be purchased from various suppliers. Custom plastic or sheet metal components can be molded or cut by any number of manufacturers. Even power cables, simple USB cables, or something like a computer mouse can easily be replaced by an equivalent.

    Some essential VxSuite components are unique to a single supplier or a small set of suppliers, however, making them at least medium criticality. When there is a single supplier, the product cannot be built as designed without the support of that supplier. Additionally, a single supplier creates a direct possible supply chain attack vector.

    Example 1: The embedded scanner in VxScan is manufactured and sold only by Peripheral Dynamics, Inc. Without being able to source the scanner from them, it would not be possible to build VxScan as it exists today, meaning the scanner has high criticality.

    Example 2: The case that forms the exterior of VxScan is a Pelican 1485 Air case. The product is designed around the case and, without the case, the product could not be built as-is, so the case is at least medium criticality. Conceivably, an alternative could be found, but it would not be straightforward.

    Example 3: The anodized sheet metal panels that form the interior surfaces of VxScan can be cut and anodized by hundreds of metal shops across the country, so they are not more critical as a result of their supply.

    hashtag
    Other Considerations

    hashtag
    Ability to Quality Control

    Any component can fail, but some component failures will be caught easily in quality control while others are more difficult to detect. For example, a misshapen sheet metal part will be caught in incoming parts QC or may result in the machine being not operable or not assemble-able. A slightly fraying cable, however, might perform adequately in QC but quickly deteriorate in performance. Components that are more complex, like a printer or cable, may exhibit deteriorated or even nefarious behavior that only manifests under certain conditions outside of QC.

    Simple components where failure is easily detected are less critical than complex components where failure is more difficult to detect. Due to the complexity of a subassembly like an entire laptop, we're not able to effectively QC all of its many subsystems and have to rely on the supplier for their QC more than for a simple, transparent component.

    hashtag
    Physical Security

    A seal point or hinge may be more critical than an interior panel because, if it is defective, it could break the physical security model of a device and allow someone to access a machine without tamper-evidence.

    hashtag
    Impacts on Security, Privacy, and Performance

    Each subcomponent's impact on security is mainly determined by its , as described above. The lowest impact on security would come from a subcomponent that cannot affect election data at all. The highest impact on security would come from a subcomponent that can affect election data in difficult-to-detect ways via well-known attack vectors. Subcomponents that don't handle data can also have impacts on security if they're a part of a device's physical security measures.

    Only subcomponents of the precinct components have a meaningful impact on voter privacy because all voter data is anonymized beyond the precinct system. Any subcomponent that the voter directly uses as part of the voter session or any subcomponent that is used to store vote data could affect voter privacy if compromised.

    Performance is broadly impacted by all components.

    hashtag
    Criticality Assessment Process

    VotingWorks assesses the criticality of each subcomponent when documenting the bill of materials. The various criteria described in are considered when assigning a criticality. The following decision tree governs most criticality assessments:

    1. Would the manufacturer's discontinuation of the subcomponent force major software and/or hardware changes?

      1. Yes → High

      2. No → Continue

    In cases of ambiguity or exceptional circumstances, VotingWorks applies its best judgment.

    hashtag
    Critical Components and Suppliers

    In each article describing the hardware of a specific component, some section will specify the high and medium criticality components and provide some explanation of why it is deemed critical. All unlisted components are low criticality.

    We consider the supplier of any critical component a critical supplier.

    hashtag
    Supplier Impact Analysis

    We assess supplier impact by evaluating how the loss, compromise, or substitution of a given supplier could affect the overall security, privacy, and performance of the voting system. This analysis considers factors such as the uniqueness of the supplier’s offering, the availability of alternative vendors, the supplier’s quality and compliance history, and the degree to which their components interface with election-critical data or operations. High-impact suppliers are those whose disruption would materially affect system availability or security, and they are prioritized for contingency planning, contractual protections, and regular review. Medium-impact suppliers may affect performance or timelines but have feasible alternatives. Low-impact suppliers can be substituted with minimal operational or security risk. This structured assessment supports informed procurement, bolsters risk-management planning, and enables ongoing supplier oversight.

    hashtag
    Supply Chain Risk Management Strategy

    VotingWorks follows the NIST SP 800-161 framework to meet the assurance requirements of our supply chain risk management strategy.

    Based on the criticality criteria enumerated above, the VotingWorks operations team identifies and prioritizes medium- and high-criticality components. For critical COTS components, we limit our suppliers to reputable and well-established vendors and manufacturers. When assessing whether a supplier is trustworthy, we consider several factors: length of time established; reputation for reliability; degree to which organization and manufacturing is based in the United States; the outcome of previous orders; responsiveness to issues; and their focus on critical business applications. For critical VotingWorks-specific manufactured components, for example any custom cables, we look for domestic-based manufacturers with ISO quality certifications (e.g. ISO 9001) and, where possible, prefer to perform site visits during onboarding.

    For each critical component, VotingWorks requires a warranty on defective components and a delivery timeline for all orders. Specifically, contracts with suppliers include language matching or to the effect of:

    • The supplier is required to provide a warranty for all products or services that do not conform to specification.

    • The supplier is required to provide a delivery timeline for each order.

    Suppliers for all critical components in the bill of materials are audited at the beginning and end of each hardware development cycle. If we discover disqualifying information about a supplier, VotingWorks works to identify alternative suppliers. If components are no longer available due to supply chain issues or the end of a product's lifecycle, VotingWorks works to identify alternative suppliers.

    Defective components during production are handled by:

    1. Identifying the defect

    2. Notifying the supplier

    3. Returning the defective component to the supplier for analysis

    4. Requiring an explanation from the supplier as to how the defect occurred and how it will be mitigated in the future.

    Installing Debian 12 on VxBuild

    hashtag
    Creating a Debian 12 USB Install Drive

    To install Debian 12 on the build machine (VxBuild), you will need to download the latest Debian 12 amd64 installer file here: latest Debian releasearrow-up-right.

    You should use a blank USB drive to create the install drive. The process described below will wipe any existing content.

    To create a USB install drive with the downloaded ISO file:

    1. Ensure that the USB drive is available to the system. By default, it tries to attach as the /dev/sda device. An easy way to verify this is via the following command:

    1. If the USB drive is not attached as the /dev/sda device, that’s ok. Simply replace /dev/sda with the device that your USB drive did attach to.

    • NOTE: The command below should not include any number as part of the device path. For example, if the above command returns /dev/sda1, you must use /dev/sda as the path in the next command.

    1. Now that you know the correct device path, you can create the USB install drive via the following command:

    • NOTE: At the time of this writing, the latest stable release is 12.8. Please update to the appropriate file name if you're using a newer version.

    1. Once the above command completes, you can safely remove the USB install drive from your system.

    hashtag
    Installing Debian 12 on VxBuild

    1. Before powering VxBuild on, insert the USB install drive created in the previous step.

    2. After powering VxBuild on, begin pressing F12 until it enters the boot menu. Boot the system from the USB install drive.

    3. You will be presented with the following screen. Select "Graphical install" and press enter.

    1. Select your preferred language and click "Continue".

    1. Select your location and click "Continue".

    1. Select your keyboard layout and click "Continue".

    1. Select your network device (may differ from screenshot) and click "Continue".

    1. If using a wired connection, it will configure automatically.

    2. If using a wireless connection, select a network, select WPA/WPA2 PSK, and click "Continue". Enter your wireless network password and click "Continue".

    1. Enter "VxBuild" for the hostname and click "Continue".

    1. Leave the domain name blank and click "Continue".

    1. Set the root user password and click "Continue".

    1. Enter "Vx" for the full name for the new user and click "Continue".

    1. Enter "vx" as the username and click "Continue".

    1. Enter a password for the "vx" user and click Continue.

    1. Select your timezone and click "Continue".

    1. Select "Guided - use entire disk" and click "Continue".

    1. Select the "/dev/nvme0n1" disk and click "Continue".

    1. Select "All files in one partition" and click "Continue".

    1. Select "Finish partitioning and write changes to disk" and click "Continue".

    1. Select "Yes" and click "Continue".

    1. The base OS installation will now begin. During the installation you will be asked to answer questions related to package management.

    2. Select "United States" and click "Continue".

    3. Select "deb.debian.org" and click "Continue".

    hashtag
    Grant Sudo Privileges

    The "vx" user needs to be granted sudo privileges related to configuring and initializing the build environment tools.

    1. Open a terminal window.

    2. As the "vx" user, you will temporarily log in to the "root" account.

    1. You will see your terminal window prompt change to root@VxBuild. To grant the "vx" user sudo privileges, run the following command as root.

    1. You will see your terminal window prompt change to vx@VxBuild. You are now the "vx" user instead of the "root" user. To confirm sudo privileges, run the following command:

    1. The command should return "root". This confirms sudo privileges have been granted correctly.

    CDF ERR Export

    The full election tally reports can be exported as JSON Election Results Reporting CDF results. The feature is only available for the full election results and not grouped or filtered results. The export follows the CDF specification without extensions. The CDF fields are used as follows:

    CDF Attribute
    Usage

    ElectionReport.Format

    Fixed to "summary-contest"

    ElectionReport.IsTest

    true or false depending on whether VxAdmin was in test ballot mode

    ElectionReport.SequenceStart

    Fixed to 1

    ElectionReport.SequenceEnd

    The Election Results Reporting CDF requires that identifiers be in , so all identifiers from the election definition are re-formatted to be compliant. For example, "Sample County" becomes "vx_sample-county".

    VxAdmin & VxCentralScan Hardware

    hashtag
    Overview

    hashtag
    Laptop

    VxAdmin and VxCentralScan are both laptops that connect to peripherals as needed. The laptop is a .

    <cvr-directory-name>.vxsig ← Signature on root-hash.txt
    <cvr-directory-name>/
      root-hash.txt ← hash( concatenation of all * hashes )
      4/
        4-hash.txt ← hash( concatenation of all 4* hashes )
        4d/
          4d-hash.txt ← hash( concatenation of all 4d****... hashes )
          4d6a9dad-e6d6-4a29-89bc-9ab915012b73/
            4d6a9dad-e6d6-4a29-89bc-9ab915012b73-hash.txt
            cast-vote-record-report.json
            Images
    <cvr-directory-name>.vxsig ← Signature on root-hash.txt
    <cvr-directory-name>/
      root-hash.txt
      4d6a9dad-e6d6-4a29-89bc-9ab915012b73/
        cast-vote-record-report.json
        Images
    <cvr-directory-name>.vxsig ← Signature on metadata.json
    <cvr-directory-name>/
      metadata.json
      4d6a9dad-e6d6-4a29-89bc-9ab915012b73/
        cast-vote-record-report.json
        Images
    {
      "arePollsClosed": false,
      "castVoteRecordRootHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      ...
    }

    Ballot Type

    4 bits

    Indicates the ballot type - absentee ballots are 0001 and precinct ballots are 0000

    Ballot ID Set?

    1 bit

    When true, indicates that the encoded ballot has an assigned ID that follows this bit. When false, indicates there is no ID.

    Ballot ID

    Variable, max 256 bytes

    Optional, HMPB only. Identifier for the ballot, UTF-8 encoding.

    Vote Data

    Variable

    In sequence, all the vote data for the contests indicated in the "roll call." For yes-no contests, a set bit 1 indicates the "yes option" whereas an unset bit 0 indicates the "no option." For candidate contests, includes a bit for each candidate in the contest definition in the order of the contest definition. 1 is a vote and 0 is a non-vote. If the contest allows write-ins (meaning allowWriteIns is true in the election definition), there will be additional data here, described below.

    Padding

    0 - 7 bits

    To ensure that the value in the QR code is composed of whole bytes, 0 bits are added until the data ends in a whole byte.

    HMPB Prelude

    24 bits

    The characters "VP2," which in binary appear as: 01010110 01010000 00110010

    Ballot Hash

    80 bits

    See ballot hash documentationarrow-up-right. The 80 bits represent 20 4-bit hexadecimal characters.

    Ballot Config

    Variable

    See Ballot Config Encoding.

    Padding

    0 - 7 bits

    To ensure that the value in the QR code is composed of whole bytes, 0 bits are added until the data ends in a whole byte.

    Precinct Index

    13 bits

    The index of the ballot's precinct in the election definition's list of precincts.

    Ballot Style Index

    13 bits

    The index of the ballot's ballot style in the election definition's list of ballot styles.

    Page Number

    5 bits

    HMPB only. Encodes the page number of the ballot, one-indexed.

    Test Ballot?

    1 bit

    When true, indicates a test ballot. When false, indicates an official ballot.

    BMD Prelude

    24 bits

    The characters "VX2," which in binary appear as: 01010110 01011000 00000010

    Ballot Hash

    80 bits

    See ballot hash documentationarrow-up-right. The election's ballot hash is visible on most authenticated screens on all apps. The 80 bits represent 20 4-bit hexadecimal characters.

    Ballot Config

    Variable

    See Ballot Config Encoding.

    Vote "Roll Call"

    Variable, 1 bit per contest in the election definition

    Each bit corresponds to one contest and indicates whether the voter made any selections. For example, with four contests, 1010 would indicate votes in the first and third contests but not the second and fourth.

    election definition
    Cast Vote Records
    Image Audit
    Model 2 QR codesarrow-up-right
    Level H error correctionarrow-up-right
    ballot-encoder libraryarrow-up-right

    Fixed to 1

    ElectionReport.GeneratedDate

    The generated timestamp of the report

    ElectionReport.Issuer

    The county name

    ElectionReport.IssuerAbbreviation

    The county identifier formatted as an NCName ID

    ElectionReport.VendorApplicationId

    "VxAdmin, version <code version>" where code version is the software version of the system e.g. "v4"

    ElectionReport.Status

    If the election has been marked as official in VxAdmin, "certified", otherwise "unofficial-complete"

    Party.@id

    The party identifier

    Party.Name

    The short name of the party e.g. "Libertarian"

    Party.Abbreviation

    The party abbreviation e.g. "L"

    Election.StartDate

    The date of the election

    Election.EndDate

    The date of the election

    Election.Name

    The title of the election

    Election.ElectionScopeId

    The state name formatted as an NCName ID

    Election.Type

    Either "general" or "primary"

    BallotCounts.Type

    Fixed to "total"

    BallotCounts.GpUnitId

    The county identifier formatted as an NCName ID

    BallotCounts.BallotsCast

    The total ballot count for the election

    Candidate.@id

    The candidate identifier formatted as an NCName ID

    Candidate.PartyId

    The candidate's party identifier formatted as an NCName ID

    Candidate.BallotName

    The candidate's name as it appears on the ballot in English

    Contest.@id

    The contest identifier formatted as an NCName ID

    Contest.Name

    The contest title

    Contest.ElectionDistrictId

    The district identifier of the contest's associated district formatted as an NCName ID

    ContestSelection.@id

    The option identifier formatted as an NCName ID

    BallotMeasureSelection.Selection

    The option label as it appears on the ballot in English

    CandidateSelection.IsWriteIn

    true or false depending on whether the candidate is a write-in candidate

    VoteCounts.Count

    The vote count for the specific contest selection

    VoteCounts.Type

    Fixed to "total"

    VoteCounts.GpUnitId

    The district identifier of the contest's associated district formatted as an NCName ID

    OtherCounts.Overvotes

    The overvote count

    OtherCounts.Undervotes

    The undervote count

    OtherCounts.GpUnitId

    The district identifier of the contest's associated district formatted as an NCName ID

    GpUnit.@id

    The county, state, or district identifier formatted as an NCName ID

    GpUnit.Name

    The county, state, or district name

    GpUnit.Type

    "state", "county", or for districts, "other"

    GpUnit.ComposingGpUnitIds

    • State: only the county identifier

    • County: all district identifiers

    NCName ID formatarrow-up-right
    Is the subcomponent responsible for generating or modifying highly sensitive election data?
    1. Yes → High

    2. No → Continue

  • Do either of the following apply? The unavailability of the subcomponent would force minor software and/or hardware changes OR the subcomponent connects over USB to the host operating system.

    1. Yes → Medium

    2. No → Low

  • VxAdmin & VxCentralScan Hardware
    VxScan Hardware
    VxMarkScan Hardware
    Relationship to Sensitive Election Data
    Criticality Criteria

    4d

    -

    4d hash

    4

    4d

    4d6a9dad-e6d6-4a29-89bc-9ab915012b73

    4d6a9dad-e6d6-4a29-89bc-9ab915012b73 hash

    …

    Leave the proxy information blank and click "Continue".
  • You will be asked to configure "popularity-contest". Select "No" and click "Continue".

  • The installation process will continue. Once it completes, you will be presented with a final screen confirming that it was successful.

  • Remove the USB drive and click "Continue".

  • The system will reboot and automatically start Debian 12.

  • Log in with the "vx" user and password you created during the installation process.

  • Several basic configuration prompts will be displayed. Select "Next".

  • Select your keyboard preference and click "Next".

  • Turn off Location Services and click "Next".

  • Do not configure any online accounts. Select "Skip".

  • Click the "Start Using Debian GNU/Linux" button. The dialog will be closed.

  • lsblk /dev/disk/by-id/usb*part* --noheadings --output PATH
    dd if=/path/to/debian-12.8.0-amd64-netinst.iso of=/dev/sda bs=4M && sync
    su -
    <Enter root user password>
    echo "vx ALL=NOPASSWD: ALL" > /etc/sudoers.d/vx
    exit
    sudo whoami

    When fixes require certification by the appropriate agencies, notably the Election Assistance Commission, VotingWorks works with these agencies to certify the fixes.

  • VotingWorks privately works with affected jurisdictions to deploy mitigations and fixes.

  • VotingWorks assigns a CVE for the vulnerability and publishes the vulnerability on the disclosure page, giving credit to the reporter if they choose to take credit. VotingWorks reserves the assignment of a CVE to confirmed security issues on products that have not been end-of-life’d.

  • Ethernet MAC Addresses

    With networking protections in place like they are on a production machine, this issue would not exist. Even if it did, it only allows an attacker to determine the MAC address of an Ethernet port, which isn't a threat.

    HTTP Methods Allowed (per directory)

    With networking protections in place like they are on a production machine, this issue would not exist. VxSuite uses HTTP internally within each component, so with networking protections turned off, it is obvious that allowed HTTP methods can be detected. This isn't an issue on a production system.

    HyperText Transfer Protocol (HTTP) Information

    With networking protections in place like they are on a production machine, this issue would not exist. Even if an attacker accessed this information, it isn't confidential.

    KVM / QEMU Guest Detection (uncredentialed check)

    This finding isn't relevant on a production machine, which is not a VM. This is a VM only because of the vuln-scan testing setup.

    Nessus SYN scanner

    With networking protections in place like they are on a production machine, this issue would not exist.

    Nessus Scan Information

    This only indicates that a particular Nessus plugin is running to determine running services.

    OS Identification

    With networking protections in place like they are on a production machine, this issue would not exist. Even if it did, it only allows an attacker to determine the operating system running on a VxSuite component, which is already public information.

    Service Detection

    With networking protections in place like they are on a production machine, this issue would not exist. Even if it did, the services that are running on a VxSuite component are publicly documented and it is not considered a threat for an attacker to know them.

    TCP/IP Timestamps Supported

    With networking protections in place like they are on a production machine, this issue would not exist. Even if it did, this only allows an attacker to determine the uptime of the VxSuite component, which is not confidential information.

    Traceroute Information

    With networking protections in place like they are on a production machine, this issue would not exist.

    Web Server No 404 Error Code Check

    The web server in question is used only for internal purposes of the VxSuite component, it is never presented as a public web site. Thus, whether it returns a 404 code or not is not important.

    Web Server robots.txt Information Disclosure

    The web server in question is used only for internal purposes of the VxSuite component, so the robots.txt file is irrelevant.

    10114arrow-up-right

    ICMP Timestamp Request Remote Date Disclosure

    With networking protections in place like they are on a production machine, this issue would not exist. Even if it did, it only allows an attacker to collect the current clock of the machine, which is not a problem.

    45590arrow-up-right

    Common Platform Enumeration (CPE)

    This only indicates that a particular Nessus plugin is running to determine platform properties.

    54615arrow-up-right

    Device Type

    With networking protections in place like they are on a production machine, this issue would not exist. Even if it did, it only allows an attacker to determine what kind of devices this is (manufacturer, CPU power, etc.). This is considered public information, so is not a threat.

    Laptop keyboard and screen
    Laptop ports

    The relevant hardware interfaces are:

    • Smart Card Reader - Enables reading and writing to smart cards, which is the basis for authentication in VxSuite

    • USB Ports - Allows connecting to the peripherals for scanning or printing

    • HDMI Port - Allows connecting the laptop to an external display, which is most often used to enlarge the adjudication interfaces when adjudication is performed by a group of people

    While not strictly necessary, VxAdmin and VxCentralScan are bundled with a mouse and a USB hub for ease of use. A USB A-B cable is included to connect to the peripherals.

    hashtag
    VxAdmin

    VxAdmin connects to a printer for the purposes of printing reports. The printer includes an RJ45 (ethernet) port which is blocked by a port blocker because network connectivity is not required by the system.

    VxAdmin fully connected with mouse, hub, charger, USB cable, and printer

    hashtag
    VxCentralScan

    VxCentralScan connects to a batch scanner for batch scanning. The scanner is either the smaller Ricoh fi-8170 or the larger Ricoh fi-7600. Ballots are loaded into the hopper and then, after a scan is triggered from the application, the scanner processes the ballots one-by-one, sending images to the application for interpretation.

    Both batch scanners can be used with Ricoh imprinters (not pictured) which allow printing an identifier on each ballot as it's exiting the scanner, which can be useful for certain types of post-election audits.

    The batch scanner is powered through an APC BN1500M2 UPS (Uninterruptible Power Supply) to ensure that the scanner can operate in variable power environments.

    The fi-8170 includes an RJ45 (ethernet) port which is blocked by a port blocker because network connectivity is not required by the system.

    VxCentralScan fully connected with mouse, hub, charger, USB cable, scanner (fi-8170), and power backup

    hashtag
    Bill of Materials

    All components for VxAdmin and VxCentralScan are commercial-off-the-shelf (COTS) components. Data sheets and related documentation are available in the documentation repositoryarrow-up-right.

    hashtag
    Shared Components (Laptop & Accessories)

    Manufacturer
    Component
    Mfr. Part Number
    Criticality

    HP

    Elitebook 840 11" G11 Laptop

    B43P6UP#ABA

    High

    Tripp Lite

    4-Port Ultra-Slim USB Hub

    U360-004-SLIM

    Medium

    Logitech

    B100 Mouse

    910-006061

    hashtag
    VxAdmin Components (Printer)

    Manufacturer
    Component
    Mfr. Part Number
    Criticality

    HP

    LaserJet Pro 4001dn Printer

    2Z600F#BGJ

    Medium

    Lindy

    RJ45 Port Blocker

    40471

    Low

    hashtag
    VxCentralScan Components (Scanner)

    VxCentralScan can be used with either the Ricoh fi-8170 or the Ricoh fi-7600, but does not need both. Each scanner can be paired with one of the two imprinters listed below.

    Manufacturer
    Component
    Mfr. Part Number
    Criticality

    Ricoh

    fi-8170 Small Desktop Scanner

    PA03810-B055

    High

    Ricoh

    fi-819PRB Imprinter (for fi-8170)

    PA03810-D201

    Medium

    Ricoh

    fi-7600 Large Desktop Scanner

    PA03740-B505

    hashtag
    Laptop Specification

    The laptop is a custom configuration of the widely available HP Elitebook 840 14" G11 laptop. B43P6UP#ABA is the HP SKU of the VotingWorks configuration, which includes the following:

    Component
    Configuration

    Processor

    Intel® Core™ Ultra 5 Processor 125U

    Memory (RAM)

    8GB (1x8GB) DDR5 5600 SODIMM Memory

    Storage (SSD)

    256GB PCIe NVMe Solid State Drive

    Display

    14" WUXGA UWVA LED (300 nits)

    Battery

    56Wh Capacity

    Webcam

    None

    hashtag
    Discussion of Critical Components

    As listed in the bill of materials above, the high criticality components are as follows:

    • HP Elitebook 840 11" G11 - As the processor and data store for ballot data and other tallies, the laptops are one of the most critical components in the entire system. HP is the only manufacturer. VotingWorks is an official OEM partner of HP in order to work closely together to ensure the quality and configuration of the laptops.

    • Ricoh fi-7600 & fi-8170 - As the source of ballot images for VxCentralScan, the Ricoh scanners are highly sensitive and critical components.

    The medium criticality components and the reasons for their classification are as follows:

    • Tripp Lite Ultra Slim USB Hub - Manages flow of data between laptop and peripherals.

    • Logitech B100 Mouse - Does not directly handle election data but does plug into a USB port, thus it could still pose a USB attack vector.

    • Monoprice USB A-B Cable - Manages flow of data between laptop and peripherals.

    • HP LaserJet Pro 4001dn - The VxAdmin printer is responsible for printing reports from VxAdmin and therefore handles highly sensitive election information. All reports from VxAdmin can be exported as PDFs and printed elsewhere, so it is not strictly necessary for the operation of the system and thus is not the highest criticality.

    • Ricoh fi-760PRB & fi-819PRB - The imprinters that pair with the Ricoh scanners are not involved in generating ballot data, so they cannot influence the interpretation of ballots when used according to instructions. The imprinted identifiers are important for post-election audits, however, so the imprinters are security-sensitive components.

    custom configured HP Elitebook 840 14" G11

    Medium

    LORELEI

    Headphones

    X6

    Low

    Williams Audio Visual

    T-Coil Neckloop

    NKL-001

    Low

    VxMarkScan Function

    VxMarkScan is the system's ballot marking device. It allows all voters to make selections in various interaction modes, print their ballot, verify their ballot, and cast their ballot independently. VxMarkScan is not a tabulator - the cast ballots must be later tabulated at VxCentralScan.

    hashtag
    Configuration

    VxMarkScan is configured with a signed election package exported from VxAdmin. The election definition defines the ballot styles that will be available to voters. The election definition also includes the translations defined for text on the ballot, while the app strings file contains the translations for other text shown on screen. The election package's audio files are played for the voter in audio-mode.

    circle-info

    User Manual Reference:

    hashtag
    Precinct Selection

    VxMarkScan is not fully configured until the election manager selects a precinct for the device. When polls are open, VxMarkScan will only allow marking ballots in the ballot styles for the configured precinct. The election manager may configure VxMarkScan to "All Precincts" in which case all ballot styles are available.

    If the election definition only has one precinct, the precinct will be automatically selected.

    The precinct selection can always be changed on VxMarkScan by an election manager, even while polls are opened.

    hashtag
    Ballot Mode

    After initial configuration, VxMarkScan is in test ballot mode. The election manager can toggle between test ballot mode and official ballot mode. In official ballot mode, the ballots printed at VxMarkScan will be official ballots. In test ballot mode, the ballots printed at VxMarkScan will be test ballots.

    Switching between ballot modes clears the printed ballot count and resets the polls to closed. The election manager can switch from test ballot mode to official ballot mode at any time.

    hashtag
    Unconfiguring

    VxMarkScan can be unconfigured by an election manager or system administrator.

    hashtag
    Polls Management

    After configuration, polls are initially closed. When polls closed, voting is not allowed on VxMarkScan.

    Poll workers open the polls to allow voting. Once polls are opened, polls can only return to the initial polls closed state while remaining configured by switching between test and official ballot mode.

    Poll workers close the polls when voting should no longer be allowed. Polls are closed until VxMarkScan is unconfigured or switched from one ballot mode to another, with one exception discussed below.

    VxMarkScan also allows poll workers to pause voting a.k.a. suspend the polls. While voting is paused, no voting sessions can be started. Voting can be resumed, after which the polls are back in the standard polls opened state. Pausing voting might be used in an early voting model between voting days or, in the case of an emergency, to pause voting while the emergency is resolved. The poll worker may chose to close polls directly from voting paused instead of resuming voting.

    If the polls have been closed, the only possible way for the polls to be re-opened is if a system administrator resets the polls to paused. Only the system administrator may do this - poll workers and election managers cannot - per the allowance in VVSG 2.0 1.1.7-E. Once polls have been reset to paused by the system administrator, voting may be resumed by a poll worker. The goal of this flow is to allow voting to continue after a poll worker has prematurely closed the polls.

    circle-info

    User Manual Reference:

    hashtag
    Voting Sessions

    When polls are opened, poll workers can enable voting sessions on behalf of voters. The poll worker selects one of the available ballot styles and loads a blank piece of thermal paper into the front input tray.

    The voter navigates through the contests on their ballot style sequentially, with controls to advance to the next contest or go back to the previous contest. The contest information presented to the voter includes the contest title, the contest district, the number of selections allowed, the number of selections remaining, the contest options, the candidates' parties if applicable, and the descriptions of any ballot measures (VVSG 2.0 7.3-C).

    Voters may leave contests blank or undervoted but are prevented from overvoting contests. If the voter attempts to mark an overvote, they will be presented a warning and instructed to deselect another selection if they want to make the new selection (VVSG 2.0 7.3-H). Previous selections are never automatically deselected.

    If the contest allows write-ins, they may input a write-in name via a virtual keyboard.

    After working through the entire ballot, the voter will then review all their selections. Any undervotes will be flagged for the voter (VVSG 2.0 7.3-I) but may be ignored. If the voter does want to make any changes, they can navigate back to any contest, make changes, and return to the review stage (VVSG 2.0 7.3-F). Once the voter is satisfied with their selections, they may print their ballot.

    The thermal printer prints a ballot, presents it to the voter, and prompts them to once again review their selections. This final review differs from the initial review in two ways. First, the printed ballot is being physically presented to the user which creates a voter-verified paper trail. Second, the selections being reviewed are a result of the actual interpretation of the ballot rather than simply the selections made by the voter. As a result, even when a voter is unable to verify their printed paper ballot visually they are still able to verify the ballot through another interaction mode. Once the voter is satisfied with their second round of review, they may cast their ballot which is ejected into the attached ballot box.

    If the voter finds a problem in their ballot during the final review stage, they must spoil the ballot. They are prompted to get help from a poll worker who can help them spoil their ballot and load a new, blank sheet. Once the blank sheet is loaded, the voter returns to the initial review stage from which they can edit selections before reprinting, reviewing, and casting their ballot.

    While the paper ballot is being presented to the voter, they are supposed to leave it in the scanner so it can be ejected into the ballot box when they cast their ballot. Many voters will naturally remove the ballot from the scanner, however, and cannot cast their ballot until they re-insert the ballot. When they do insert their ballot, it is scanned again and they are returned to the final review stage.

    It's possible that a voter removes their ballot and does not re-insert it before the voting session times out. In this case, it's possible for a poll worker to initialize a session by re-inserting an already printed ballot rather than by selecting a ballot style. The already printed ballot is scanned and the voter is dropped directly on the final review screen.

    If a re-inserted ballot is somehow not compatible with the machine - wrong election, wrong precinct or wrong ballot mode - the user is alerted and the ballot is rejected out the front.

    If a poll worker card is inserted during a voting session the poll worker can deactivate the current session and spoil any current ballot.

    From the poll worker screen a poll worker may choose "Insert Printed Ballot" in order to scan a previously printed ballot and start a new voter session at the "Review Ballot" stage of the flow diagram above.

    circle-info

    User Manual Reference:

    hashtag
    Voter Privacy

    The voter's choices do not persist on VxMarkScan after the end of the voting session. Other than the increase in the count of printed ballots, the only data that persist after each voting session are the relevant log events for authentication, casting a ballot, invalidating a ballot, and hardware state changes. The voter's selections or any voter actions that may trigger selections (such as touch screen presses, accessible controller presses, PAT input events) are not included in logging or otherwise persisted. After the voting session is complete, their printed ballot is the only record of their selections. Throughout the voting session, the physical privacy shield restricts others' view of the voter's actions and their printed ballot.

    hashtag
    Display Formats & Interaction Modes

    VxMarkScan supports voting sessions in various display formats and interaction modes.

    circle-info

    User Manual Reference:

    hashtag
    Visual and Enhanced Visual Formats

    The voting session begins in visual mode with the following default settings:

    • Text Size - Medium, which corresponds to between 14pt - 16pt, meeting the default text size requirement specified in VVSG 2.0 7.1-G.

    • Contrast - Medium, which is at least a 10:1 contrast for all informational elements, meeting the default contrast requirement specified in VVSG 2.0 7.1-C

    The voter can update the Text Size to Small, Medium, Large, or Extra-Large, which map to the four discrete text sizes defined in VVSG 2.0 7.1-G. Changing the text size changes the size of all informational elements including buttons, icons, and layout (VVSG 2.0 7.1-H) because all such elements are sized relative to the base font size. The font is always sans-serif (VVSG 2.0 7.1-J).

    If there's too much content on a page to fit all on screen at once, which happens most commonly in large or extra-large text size, the interface introduces a large "More" button to indicate there are more contest option to scroll through. The interface never lays out content in a way which requires horizontal scrolling.

    The voter can update the Contrast from medium contrast to low contrast, high contrast with black background, or high contrast with white background corresponding to the contrast options specified in VVSG 2.0 7.1-D. The contrast changes apply to all elements on screen.

    In addition to text, color and icons are used on screen to guide voters. In conformance with color conventions (VVSG 2.0 7.1-E), red indicates danger, yellow indicates warning, and green indicates success. For example, choosing to spoil one's ballot is a red button. Purple is generally used as the primary color to indicate the recommended next step. In high contrast modes, the interface is entirely black and white to support the 20:1 contrast ratios. Icons are used on buttons to provide an additional visual cue, but are always paired with text (VVSG 2.0 7.3-L).

    Ending a voting session will automatically reset all display settings to defaults (VVSG 2.0 7.1-A). The voter can change or reset the display settings to defaults at any time (VVSG 2.0 7.1-B).

    In visual mode, when a voter makes a selection it is indicated in three ways:

    • Highlighting the selection in a contrasting color

    • Updating the icon from an unchecked to a checked box

    • Decrementing the number of remaining votes allowed shown on screen

    Once a voter has used all their votes in a race, the progress button at the bottom of the screen to advance to the next race is also highlighted to encourage the voter to proceed.

    hashtag
    Touch Interaction Mode

    Voters usually choose to use the touchscreen to vote. The voter taps buttons to move between contests and through the stages of the voting flow. The voter taps list items on each contest page in order to make selections. Touch areas never overlap and are sized to meet minimums described in VVSG 2.0 7.2-I. Touch areas require that the user's touch begins and ends within the touch area to activate, meaning that dragging a finger across a touch area will not activate the touch area, in order to avoid accidental activation (VVSG 2.0 7.2-H).

    When there's more content on a page than can fit on one screen, the voter can scroll through the screen in one of two ways. First, they can tap the "More" button which acts as both the visual indicator that there are more contest options or contests. Second, they can use a swiping motion on the screen to move up or down. Swiping to see more contest options or contests is VxMarkScan's only touch screen gesture. It cannot be used horizontally to navigate between contests or pages and (VVSG 2.0 7.2-E).

    hashtag
    Audio Tactile Mode - Accessible Controller

    VxMarkScan has a permanently attached accessible controller that can be used to navigate the ballot instead of using the touchscreen directly. The left and right buttons are used to navigate between contests and other screens while the up and down buttons are used to navigate between contest options or contests within each screen. The controller has a help button which will navigate to a help interface that explains the function of each button on the controller when pressed.

    The currently focused element on screen is highlighted in visual mode or read aloud in audio mode. When navigating through selections on a screen large enough to be scrollable, the screen will automatically scroll to keep the focused element in view.

    The accessible controller is integrated with the application via a hardware daemon that is always running. The daemon is continuously listening for input events from the controller. Each event is converted into virtual keyboard presses which are then handled by the frontend rendering agent just as a web browser might handle arrow key inputs.

    hashtag
    Limited Dexterity Mode - PAT Input

    VxMarkScan has a PAT (personal assistive technology) input port into which a voter can plug in their own two-switch adaptive input such as a sip-and-puff device. When a PAT input is attached during a voting session, VxMarkScan will enter a calibration flow where the voter will map their two inputs to "move" and "select." Different voters can calibrate their sip & puff devices differently such that sip is "move" for one and "select" for another.

    Once calibrated, the voter can use the two inputs to navigate through the ballot. The "move" input advance the focus on screen to the next element and the "select" input is the equivalent of a tap in touch interaction mode. Just as with the accessible controller, the currently focused element on screen is highlighted in visual mode or read aloud in audio mode.

    The PAT input is integrated with the application via a hardware daemon that is always running. The daemon is continuously listening for input events from an attached device. Each event is converted into virtual keyboard presses which are then handled by the frontend rendering agent just as a web browser might handle Tab and Enter.

    hashtag
    Audio Format

    As an alternative to the visual formats, the voter can listen to their ballot in an audio format. VxMarkScan includes a headphone port and headphones which, when attached, will automatically play audio to guide the voter's ballot navigation. The audio includes information about the election, contests, and contest options equivalent to the information displayed on screen in visual mode. The audio also includes prompts and explanations for how to navigate the ballot that are equivalent to the cues in layout and highlighting on screen in visual mode. These instructions include but are not limited to:

    • how to start voting

    • how to make selections in a contest

    • how to navigate the review screens

    • how to use the accessible controller

    The voter can adjust volume up and down or speech rate up and down with buttons on the accessible controller. Volume and rate defaults and options are calibrated according to VVSG 2.0 7.1-K. The voter can also pause and resume audio with a button on the accessible controller.

    Blind or visually impaired voters can use the audio track to review their printed ballot. The printed ballot is scanned and interpreted on its way out of the printer, and the resulting interpretation is the basis for the audio played in the second review state. As a result, blind or visually impaired voters are able to verify their paper ballots just as seeing voters are able to verify their paper ballots.

    hashtag
    Language Support

    VxMarkScan supports switching the language for the current voting session to any language supported in the current election package. When the language is changed, all text on the ballot, all text shown on screen, and text read in audio mode to guide the voter will switch to the new language. The language can be changed at any time during a voting session. The language selection resets automatically after each voting session or can be reset by the voter at any time..

    If a language other than English is set when printing the ballot, the ballot will show all information in both the current language - for the purpose of the voter's review - and in English - for ease of adjudication and audits.

    hashtag
    Printer Access Control

    VxMarkScan's printer and scanner are covered by the printer cover which can be opened at any time in order to clear a paper jam or clean the scanner. In order to prevent unauthorized access, pursuant to VVSG 2.0 12.1-B, VxMarkScan produces a jarring, audible alarm if the printer cover is opened while polls are opened. The alarm should alert a poll worker that something is wrong. A poll worker then inserts their card, which silences the alarm, and follows on screen instructions to close the printer cover.

    Because authentication is required for the poll worker to open the printer cover without triggering an alarm, poll workers are instructed on screen to authenticate when clearing a paper jam. When polls are closed, the alarm is not active, so cleaning and setup can take place without triggering the alarm.

    Access Control

    hashtag
    Certification of VxSuite Components

    VxSuite is composed of individual machines, namely VxAdmin, VxCentralScan, VxMarkScan, and VxScan, as well as smart cards for authentication. Each machine and each smart card has a unique 256-bit ECC private key (or keys in the case of smart cards) stored in tamper-resistant hardware, plus one or more X.509 certificates for the corresponding public key (or keys) with relevant attributes bound.

    This means that every VxSuite component can prove its authenticity, notably to any other VxSuite component. For example, a smart card can prove to a VxAdmin that it is a valid election administrator card for a particular election, or a VxScan can export digitally signed cast vote records, which a VxAdmin can then verify are authentic before importing.

    VxScan Function

    VxScan is the system's precinct scanner into which voters cast their ballots directly.

    hashtag
    Hardware Management

    hashtag
    Printer Management

    86420arrow-up-right
    43111arrow-up-right
    24260arrow-up-right
    56877arrow-up-right
    11219arrow-up-right
    19506arrow-up-right
    11936arrow-up-right
    22964arrow-up-right
    25220arrow-up-right
    10287arrow-up-right
    10386arrow-up-right
    10302arrow-up-right

    Medium

    Monoprice

    USB-A to USB-B 2.0 6ft Cable

    5438

    Medium

    High

    Ricoh

    fi-760PRB Imprinter (for fi-7600)

    PA03740-D101

    Medium

    GoldenMate

    Uninterruptible Power Supply

    UPS 1000VA/600W

    Low

    Lindy

    RJ45 Port Blocker

    40471

    Low

    Near Field Communication

    None

    WWAN (Cellular)

    None

    WLAN (Wi-Fi)

    None

    Fingerprint Sensor

    None

    Smart Card Reader

    Included

    Country of Origin

    TAA Designated

    Certification relationships work as follows:
    • VotingWorks directly certifies the type of every component, i.e., VxAdmin machine, VxCentralScan machine, VxMarkScan machine, VxScan machine, or smart card. This makes it such that only components that are “blessed” by VotingWorks can successfully communicate with each other. This is also important for defense-in-depth and separation of privileges, as one VotingWorks component type cannot act like another, e.g., a VxScan cannot sign an election configuration package like a VxAdmin can. Because machine certificates include a machine ID, it's also the case that, say, VxScan SC01 cannot sign CVRs as VxScan SC02.

    • VotingWorks further certifies every VxAdmin as bound to a particular jurisdiction, e.g., Warren County, Mississippi. This is important because VxAdmins program smart cards and should not be able to program cards for other jurisdictions.

    • Every smart card, in addition to being certified directly by VotingWorks, is certified by a VxAdmin during card programming. A card’s VxAdmin-issued certificate indicates 1) the jurisdiction that the card is bound to, 2) which user role the card has been programmed for, i.e. system administrator card, election manager card, or poll worker card, and 3) in the case of election manager and poll worker cards, the specific election that the card is bound to.

    As a diagram:

    VxCentralScan, VxMarkScan, and VxScan, unlike VxAdmin, aren’t bound to a jurisdiction by VotingWorks. They’re bound and unbound to jurisdictions as they’re configured and unconfigured by election managers. When an election manager configures a VxCentralScan, VxMarkScan, or VxScan for an election, the machine persists in its datastore the jurisdiction of the election manager card used to unlock it and then only accepts cards from that jurisdiction. When the machine is unconfigured for that election, the machine returns to a jurisdiction-agnostic state. This allows one jurisdiction to lend its unconfigured equipment to another, without giving a jurisdiction any power over machines configured for a different jurisdiction.

    hashtag
    Smart Card Keys and Certificates

    As described above, programmed smart cards have two certificates, one issued by VotingWorks and one issued by VxAdmin. We generate two key pairs on the card, one for each certificate. We could have chosen to certify the same key twice, but as will be described below, we wanted to have different usage policies for the two private keys, thus the issuance of certificates against two different keys. Smart cards also have PINs (with the exception of poll worker cards, unless an election official chooses to enable poll worker card PINs). These interface as follows:

    • The private key slot associated with the card’s VotingWorks-issued certificate is not PIN-gated, so anyone can immediately verify that a card is a VotingWorks-certified card.

    • The private key slot associated with the card’s VxAdmin-issued certificate is PIN-gated, so authentication requires PIN entry.

    • The card’s VxAdmin-issued certificate, on the other hand, is not PIN-gated, so it’s possible for a VotingWorks machine to know the card’s type and which election it’s bound to even before a PIN is entered. This allows the machine to display error messages like “election mismatch” immediately after card insertion and before PIN entry.

      • This does mean that an attacker could load a fake certificate onto a card such that the machine, at worst, displays an incorrect error message, but nothing more. Authentication would still fail as the public key in the certificate would not match the private key on the card. We take care not to fully trust the information in this certificate until we complete authentication.

    We’ve taken inspiration from the NIST Personal Identity Verification (PIV) standard but haven’t strictly adhered to it. Our use case differs from the PIV standard in a number of ways, most notably in that cards are certified by two entities (VotingWorks and VxSuite), rather than just one. We also don’t need VxSuite smart cards to be interoperable with other PIV systems.

    The recommended access control policy by role for system administrator, election manager, and poll worker cards is documented in the user manual (Smart Cards and User Rolesarrow-up-right). Deviating from this recommended access control policy can result in a violation of the principle of least privilege and users gaining access to voting system functionality that is not intended for them. For example, a poll worker could have access to unconfiguring a voting machine if provided a smart card programmed for a different role.

    hashtag
    Vendor Cards

    There's one additional card type, the vendor card, and it differs slightly in its cert structure from the other card types. VotingWorks uses vendor cards to access the vendor menu on machines, for low-level operations like machine key rotation. Vendor cards are programmed directly by VotingWorks and not by VxAdmin. Because of this, vendor cards do not have a VxAdmin-issued cert, but rather, a second VotingWorks-issued cert. The general term that we use for this second cert across all card types is the identity cert, as it confers user role, i.e., identity.

    Vendor cards can be programmed to be either jurisdiction-specific or jurisdiction-agnostic.

    hashtag
    Private Key Storage

    We store our root VotingWorks certificate authority (CA) private key encrypted in a password vault, usable only by a few authorized engineers.

    VxAdmin, VxCentralScan, VxMarkScan, and VxScan are all built on devices with a Trusted Platform Module (TPM) 2.0, a chip that ships standard on modern Intel and AMD hardware. The TPM can keep cryptographic material secret inside its tamper-resistant boundary until a certain set of system conditions are met. Only once the TPM determines that the system meets a set of appropriate conditions—correct bootloader, kernel, kernel command line, etc.—does the TPM allow an application to ask it to perform signing operations with its contained secret key.

    Our smart cards are JCOP 4 Java Cards, version 3.0.5. These Java Cards can generate 256-bit ECC key pairs such that the private key never leaves the card, while the public key is exported. The cards are capable of self-destructing if someone attempts to extract the private key at the hardware level.

    hashtag
    Smart Card PINs

    Vendor cards, system administrator cards, and election manager cards always have PINs. Poll worker cards do not have PINs by default but can if the system administrator enables them.

    PINs are auto-generated random 6-digit numbers, guaranteed not to be weak (e.g. not 11111, 123456, 121212).

    After 5 incorrect PIN attempts, users have to wait 15 seconds before they can try again. For every incorrect PIN attempt after that, the wait time doubles (15 seconds → 30 seconds → 60 seconds and so on). After 15 incorrect PIN attempts, the card is completely locked and has to be reprogrammed. System administrators can adjust the number of incorrect PIN attempts allowed without lockout as well as the starting lockout duration. The number of incorrect PIN attempts is stored on the card in a tamper-resistant location (as opposed to on the machine), meaning that taking a card to another machine to gain extra attempts will not work. Removing and reinserting a card restarts the lockout timer.

    hashtag
    Certificate Format

    The certificates that we use are effectively vouchers—a certificate authority (CA) vouches that a public key has certain properties, for example that it is the public key of an election manager card for a particular election. This vouching is done by signing data containing the public key and those properties. We use X.509 certificates as they are broadly used and well supported.

    While we could use existing X.509 fields like Organization, Organizational Unit, and Serial Number, and wedge our data into those types, overloading existing fields that don’t quite match isn’t ideal and could lead to security issues from type confusion.

    Instead, we use our own fields. We’ve registered with IANA to have a VotingWorks enterprise object identifier (OID), which is effectively a prefix for OIDs of the form 1.3.6.1.4.1.32473.123, where 1.3.6.1.4.1.32473 is the enterprise OID for an example organization, and 123 is the 123rd field defined by that organization.

    Our IANA-assigned Private Enterprise Number (PEN) is 59817, which means that the enterprise OID, fully-prefixed, is 1.3.6.1.4.1.59817. See https://www.iana.org/assignments/enterprise-numbers/?q=59817arrow-up-right.

    Our custom fields are:

    • 1.3.6.1.4.1.59817.1 — Component = admin, central-scan, mark-scan, scan, or card (the first four referring to machines)

    • 1.3.6.1.4.1.59817.2 — Jurisdiction = {state-2-letter-abbreviation}.{county-or-town} (e.g., ms.warren or ca.los-angeles)

    • 1.3.6.1.4.1.59817.3 — Card type = vendor, system-administrator, election-manager, poll-worker, or poll-worker-with-pin (vendor, system administrator, and election manager cards always have PINs)

    • 1.3.6.1.4.1.59817.4 — Election ID = The ID of the election that an election card was programmed for*

    • 1.3.6.1.4.1.59817.5 — Election date = The date of the election that an election card was programmed for

    • 1.3.6.1.4.1.59817.6 — Machine ID = A VxAdmin, VxCentralScan, VxMarkScan, or VxScan machine ID

    *This is not the same election ID as displayed in machine footers. The election ID as it pertains to cards is the id field in the election definition. The election ID as it pertains to machine footers is actually a hash, specifically <first-7-digits-of-hash-of-election-json>-<first-7-digits-of-hash-of-election-zip>. The reason for not using the latter in card certificates is to avoid having to reprogram cards after election package edits for what is conceptually still the same election.

    hashtag
    Certificate Expiries

    X.509 certificates eventually expire. We use the following expiry times:

    • Certificates directly issued by VotingWorks: 100 years

    • VxAdmin-issued system administrator card certificates: 5 years

    • VxAdmin-issued election manager and poll worker card certificates: 6 months

    • VotingWorks-issued vendor card certificates: 7 days

    This means that system administrator cards will automatically expire after 5 years, election manager and poll worker cards will automatically expire after 6 months, and vendor cards will automatically expire after 7 days.

    hashtag
    Configuration and Authentication Process

    hashtag
    Configuration at VotingWorks Facility

    Configuration of VxSuite components begins at a secure VotingWorks facility. At this facility is a VotingWorks certification terminal, VxCertifier. VxCertifier is a fully offline air-gapped terminal with access to the root VotingWorks private key.

    Using VxCertifier, VotingWorks prepares and certifies smart cards for use with VotingWorks machines:

    1. VotingWorks installs the appropriate security module code on the card.

    2. VotingWorks instructs the smart card to generate a key pair and export the public key.

    3. The root VotingWorks CA certifies the card public key and saves the resulting certificate onto the card.

    The card is now VotingWorks-certified but “blank” from the perspective of VotingWorks machines.

    VotingWorks also certifies its machines at this facility. After a machine has been imaged with our latest software release, the machine boots into a configuration wizard. The software image includes the root VotingWorks CA certificate, so no extra work is required beyond imaging to “install” that certificate. Using the configuration wizard and VxCertifier, VotingWorks certifies machines:

    1. VotingWorks machine code instructs the machine’s TPM to generate a key pair and export the public key.

    2. VotingWorks machine code generates a certificate signing request (CSR) for that public key and writes the CSR to a USB drive.

      1. On VxAdmin, VotingWorks additionally specifies a jurisdiction. That jurisdiction is included in the CSR.

    3. The USB is plugged into VxCertifier. Through VxCertifier, the root VotingWorks CA certifies the machine public key and saves the resulting certificate onto the USB drive.

      1. VxAdmin certificates are themselves CA certificates capable of creating additional certificates (necessary for smart card programming).

    4. The USB drive is plugged back into the machine to be certified. The machine loads the certificate from the USB drive, verifies its correctness, and saves it onto its hard drive.

    5. On VxAdmin, the configuration wizard also surfaces a prompt to program a first system administrator card to bootstrap the jurisdiction as, from here on out, the machine will need to be unlocked by a system administrator card in order to program any other cards.

    Machines, a first system administrator card, and “blank” cards are shipped to jurisdictions.

    hashtag
    Smart Card Programming

    In the field, election officials use their VxAdmin and their first system administrator card to program additional smart cards. Smart card programming involves the following steps:

    1. VxAdmin retrieves the card’s VotingWorks-issued certificate and verifies that it was signed by VotingWorks using the VotingWorks CA certificate installed on every machine.

    2. VxAdmin resets the card PIN, which further causes the card to clear all of its PIN-gated key slots, essentially unprogramming it if it was previously programmed.

    3. VxAdmin instructs the card to generate a key pair and export the public key. This key pair is distinct from the key pair that VotingWorks generated.

    4. The VxAdmin CA certifies the card public key, assigning relevant attributes like the jurisdiction, card type, and election if applicable, and saves the resulting certificate to the card.

    5. VxAdmin also saves its own CA certificate onto the card (more on how this is used under Authentication).

    hashtag
    Authentication

    Smart card authentication involves the following steps:

    1. The machine retrieves the card’s VotingWorks-issued certificate and verifies that it was signed by VotingWorks using the VotingWorks CA certificate installed on every machine.

    2. The machine retrieves 1) the card’s VxAdmin-issued certificate and 2) the certificate of the VxAdmin that programmed the card, which as noted in Smart Card Programming is also loaded onto the card. The machine verifies that the former (1) was signed by the latter (2). The machine also verifies that the latter is a valid VxAdmin certificate signed by VotingWorks using the VotingWorks CA certificate, establishing a chain of trust all the way up to a trusted root.

    3. The machine verifies that the card has a private key that corresponds to the public key in the card’s VotingWorks-issued certificate by asking the card to sign a challenge with its private key and attempting to verify it with the public key.

    4. The machine verifies that the card has a private key that corresponds to the public key in the card’s VxAdmin-issued certificate by asking the card to sign a challenge with its private key and attempting to verify it with the public key.

      1. If the card has a PIN, the card will only proceed with this signature if provided the appropriate PIN. The VotingWorks machine thus asks the user for their PIN to perform this operation.

    5. Throughout this process, the machine verifies that certificate fields are valid and consistent. It also verifies that the card jurisdiction and election match the machine jurisdiction and election, where relevant.

    hashtag
    Session Time Limits

    Machines automatically lock after they’ve been left idle for 30 minutes and also automatically lock after 12 hours, even if the user has been active. The user is given appropriate heads up. System administrators can select shorter time limits.

    These time limits do not apply to unauthenticated screens like the “Insert Your Ballot” screen on VxScan.

    hashtag
    Code Links

    Refer to the following code links for more details:

    • https://github.com/votingworks/vxsuite/tree/v4.0.2/libs/autharrow-up-right — VxSuite authentication lib, a good starting point for all things authentication

    • https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/dipped_smart_card_auth.tsarrow-up-right — High-level authentication state management for VxAdmin and VxCentralScan

    • https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/inserted_smart_card_auth.tsarrow-up-right — High-level authentication state management for VxScan

    • — Java Card implementation

    • — Certificate configuration

    • — OpenSSL commands underlying various authentication and signing operations

    • — The production machine configuration wizard

    • — A summary of the scripts in the authentication lib, many of which are used for production configuration

    • — The applet that we’re installing onto our Java Cards

    VxScan includes an embedded A4 thermal roll printer which is used to print polls reports. The application communicates with the printer via a custom driver developed by VotingWorks. The application is regularly polling the printer for status, which is one of the following:
    Status
    Meaning
    Effect

    Ready

    Platen is attached and paper is detected

    Application may print normally

    No Paper

    Platen is attached but no paper is detected

    Printing disabled. A warning will be shown on poll worker screens.

    Cover Open

    Platen is not attached

    Printing disabled. If the polls are open, a warning will be shown.

    Error

    Most likely the printhead has overheated, but other hardware errors are possible. Details available in diagnostics interface.

    Printing disabled. Poll workers will not be able to operate the polls, but election managers and system administrators can still authenticate for diagnostics.

    During a polls transition, a polls report is generated and gradually sent to the printer. Documents are A4 width but of indefinite length depending on the number of contests on the ballot styles at the precinct. If the printer encounters an error or runs out of paper in the middle of a print, the poll worker will be prompted to wait or to replace the thermal roll in order to continue printing. The previous document will reprint from the beginning. In most cases, poll workers do not have to install the thermal paper roll.

    Election managers normally install the thermal paper rolls via a guided flow. They will be prompted to remove the platen, install the paper, and re-install the platen. Whenever an election manager installs a thermal paper roll, they are also prompted to print a test page. The main goal of the test print is to ensure that the election manager installed the roll in the correct orientation as it is one-sided and, if reversed, will not print anything.

    The printer roll can be loaded at any time, including when VxScan is off. It only requires opening the access door which may be sealed.

    circle-info

    User Manual Reference:

    hashtag
    Scanner Management

    VxScan scans ballots with an embedded A4/Letter document scanner which produces double-sided ballot images. The application communicates with the scanner through a custom driver developed by VotingWorks. The application sends and receives events to and from the driver, managing its transitions between scanning states (waiting, accepting, etc.) and controlling when it will or will not accept ballots.

    The embedded scanner includes a multi-sheet detector (MSD) which allows the application to reject cases of voters feeding in multiple ballots at a time. The multi-sheet detection must be calibrated at the beginning of an election based on the thickness of the ballot paper. The double sheet detection calibration flow is exposed in the election manager menu. The election manager can choose to disable double sheet detection, but it is enabled by default.

    The embedded scanner has image sensors that are calibrated at the factory and generally do not need to be recalibrated. VotingWorks recommends that users do not recalibrate the image sensors unless instructed to do so by VotingWorks support. The image sensor calibration flow is exposed in the system administrator menu.

    The scanner's cover can be opened for cleaning, during which scanning will be disabled and the application will show a warning on screen if the polls are open.

    circle-info

    User Manual Reference:

    hashtag
    Audio Management

    VxScan makes noises whenever a ballot is accepted or rejected. The ballot accepted sound is a pleasant chime and the ballot rejected sound is a jarring beep. Election managers can toggle sounds on or off.

    hashtag
    Configuration

    VxScan is configured with a signed election package exported from VxAdmin. The election definition includes the ballot layouts necessary for interpreting ballots and the system settings which indicate what type of ballot issues (e.g. overvotes) require adjudication.

    circle-info

    User Manual Reference:

    hashtag
    Precinct Selection

    VxScan is not fully configured until the election manager selects a precinct for the device. When polls are open, VxScan will only accept ballots for the configured precinct. If ballots for other precincts are cast, they will be rejected. The election manager may configure VxScan to "All Precincts" in which case ballots for all precincts will be accepted.

    If the election definition only has one precinct, the precinct will be automatically selected.

    Once polls are opened and ballots are cast, the precinct can no longer be changed. If polls are opened but ballots have not yet been cast, the precinct can still be changed but it will result in the polls resetting to closed. Resetting the polls to closed forces a poll worker to re-open the polls, which reprints the polls opened report with the new, correct precinct configuration.

    hashtag
    Ballot Mode

    After initial configuration, VxScan is in test ballot mode. The election manager can toggle between test ballot mode and official ballot mode. In official ballot mode, only official ballots can be scanned and exported CVRs will be official ballot CVRs. In test ballot mode, only test ballots can be scanned and exported CVRs will be test ballot CVRs. If allowOfficialBallotsInTestMode is set in the system settings, official ballots will be allowed in test mode but exported CVRs will still be test CVRs.

    Switching between ballot modes clears all scanned ballot data and resets the polls to closed. The election manager can switch from test ballot mode to official ballot mode at any time. When in official ballot mode after ballots have been scanned, the election manager can only switch back to test ballot mode if the CVRs have been synced to the USB drive.

    hashtag
    Unconfiguring

    VxScan can be unconfigured by an election manager or system administrator. If ballots have been scanned in official ballot mode, an election manager can only unconfigure the machine after scanned ballot data has synced to a USB drive. System administrators can unconfigure the machine at any time.

    hashtag
    Polls Management

    After configuration, polls are initially closed. When polls closed, ballots cannot be cast.

    Poll workers open the polls to allow casting ballots. Once polls are opened, polls can only return to the initial polls closed state while remaining configured in two ways. First, switching from test ballot mode to official ballot mode will reset the polls. Second, in cases where the polls are open but no ballots have been cast, the precinct can still be changed which will also reset the polls to closed. Both of these actions can be performed by election managers but not poll workers. While polls are open, ballots can be inserted by voters, scanned, and tabulated.

    Poll workers close the polls when ballots should no longer be cast. After polls have been closed, the scanner will not accept ballots and the polls cannot be opened again. Polls are closed until VxScan is unconfigured or switched from one ballot mode to another, with one exception discussed below.

    VxScan also allows poll workers to pause voting a.k.a. suspend the polls. While voting is paused, the scanner will not accept ballots. Voting can be resumed, after which the polls are back in the standard polls opened state. Pausing voting might be used in an early voting model between voting days or, in the case of an emergency, to pause voting while the emergency is resolved. The poll worker may chose to close polls directly from voting paused instead of resuming voting.

    If the polls have been closed, the only possible way for the polls to be re-opened is if a system administrator resets the polls to paused. Only the system administrator may do this - poll workers and election managers cannot - per the allowance in VVSG 2.0 1.1.7-E. Once polls have been reset to paused by the system administrator, voting may be resumed by a poll worker. The goal of this flow is to allow voting to continue after a poll worker has prematurely closed the polls.

    circle-info

    User Manual Reference: , ,

    hashtag
    Scanning

    Scanning can begin once VxScan is fully configured and polls are open. If any user authenticates, scanning will be disabled until they remove their card. If CVRs are not synced to the USB drive, or no USB drive is inserted, scanning will be disabled. Scanning will be enabled again once a USB drive with synced CVRs is detected. If the election manager has disabled continuous export then scanning will be enabled without a synced USB drive present.

    While scanning is enabled, the scanner will grab and scan paper as soon as it is detected. The scanned image will be interpreted while the ballot is still being held by the scanner. If the ballot is interpreted successfully and contains no errors, it will be ejected into the ballot box with a chime and the screen will inform the voter that their ballot has been cast.

    If the ballot cannot be interpreted, it will be rejected toward the voter. Interpretation can fail if the ballot is not a valid hand marked ballot or if the ballot enters the scanner at too much of an angle, although the paper path normally prevents significant skew. If the ballot is interpretable but is invalid due to a mismatching election, precinct, or ballot mode, it will also be rejected toward the voter.

    If the ballot is interpreted and valid, but contains some voter error, the scanner will hold the ballot out of view while the errors are presented to the voter on screen. The types of errors that are flagged are determined by the precinctScanAdjudicationReasons set in the system settings. Possible options are overvotes, undervotes, and blank ballots. In the case of overvotes or undervotes, the specific list of affected contests will be listed. The voter has the option to return the ballot to themselves or to cast it despite warnings. If there's an overvote and disallowCastingOvervotes is set in the system settings, however, the ballot can only be returned.

    If the precinctScanAdjudicationReasons includes adjudicating unmarked write-ins, which are marks in the write-in space with the associated bubble unmarked, those unmarked write-ins will be included when determining whether a contest contains an overvote. At the same time, it will be considered an undervote. For example consider a vote for one contest. If the voter only fills in an unmarked write-in, it will be considered an undervote. If the voter fills in a bubble and a separate unmarked write-in, it will be considered an overvote when warning the voter. Warning in both these cases encourages the voter to clarify their ambiguous marks. When it votes are tallied, however, unmarked write-ins are always considered undervotes at VxScan.

    Once the ballot is cast, whether immediately after interpretation or after the voter confirms to cast a ballot with errors, the image and interpretation are both saved to disk and exported to the inserted USB drive as a CDF CVR. The sheet count shown on screen will increment accordingly.

    circle-info

    User Manual Reference:

    hashtag
    Visual Settings

    The voter interface can be tuned to be more accessible to different voters:

    • Text size can be adjusted to four different sizes (VVSG 2.0 7.1-G)

    • Contrast mode can be adjusted from the default medium contrast (VVSG 2.0 7.1-C) to a high-contrast white background, high contrast black background, or low contrast (VVSG 2.0 7.1-D)

    • Language can be adjusted to any language supported by the election package

    The election package's app strings file specifies the translations that will be used to replace all on screen voter messages when the language is switched.

    After the voter casts their ballots, settings will automatically reset to the default (VVSG 2.0 7.1-A). There is also a voter option to reset settings (VVSG 2.0 7.1-B).

    hashtag
    Cast Vote Records

    VxScan exports cast vote records to the inserted USB drive continuously, after every ballot is cast, in order to avoid a lengthy export at the end of the day. All cast vote records include ballot images and images of rejected ballots are also included. If there is no USB drive in VxScan, ballots cannot be cast. If the CVRs on the USB drive are not in sync with record of ballots on disk, VxScan requires a poll worker or election manager to sync the CVRs to the USB drive. This normally occurs when a USB drive is swapped out after ballots have already been scanned.

    Continuous export can be disabled by an election manager if need be, for example if a USB drive turns out to be slow or no USB drive is available. If continuous export is disabled, VxScan can be used without a USB drive inserted.

    CVRs can be exported directly from the election manager menu, in which case they export all at once.

    circle-info

    User Manual Reference:

    hashtag
    Reports

    On polls open, polls closed, voting paused, and voting resumed, VxScan prints a report via the thermal printer. The poll worker has the option to reprint additional report as many times as they need. The latest polls report can be cast as long as no ballots have since been cast. For example, the polls opened report can be printed as long as zero ballots have been cast. The polls closed report can be printed indefinitely, because no ballots can be cast after polls are closed. Reports will have both the timestamp of the polls transition and of the report printed, so reports printed at a later time are distinguishable.

    For details about the format of the polls reports, see VxScan Polls Reports.

    For polls opened and polls closed reports, the vote interpretations of all ballots are tallied together. In the case of polls opened reports, the tallies should always be zero forming a zero report. It is impossible to have any ballots scanned already at the time of polls are opened, because the scanner is disabled until polls are opened. Pursuant to VVSG 2.0 1.1.3-B, however, in the impossible event that non-zero totals are detected on the machine when the poll worker attempts to open the polls, an error will be presented to the poll worker, and logged, and they will be unable to open the polls.

    Tallies for the polls closed report are created by iterating through the data store's table of cast vote records and forming totals of votes for contest options, undervotes, overvotes, and total ballots cast. The process is the same as on VxAdmin but with far fewer steps because there are no write-in adjudication results to consider and no manual tallies. All marked write-ins are grouped as a generic "Write-In" count in reports. All unmarked write-ins are considered as undervotes.

    For voting paused and voting resumed reports, only a total ballot count is included as opposed to vote tallies.

    There are no persistent contest option registers. Contest option counts (as show up in the zero report) are calculated by summing the data across all CVRs at the time the report is generated.

    https://app.gitbook.com/s/JtZutzGTdCzsGITrdiph/vxmark/voting-sessions

    Software Overview

    VotingWorks software is open-source, which means that the code is free and publicly available. All code written by VotingWorks and almost all dependencies are open-source, with the notable exception of third-party firmware for various hardware components.

    All system components - VxAdmin, VxCentralScan, VxMarkScan, VxScan - run different application code but have fundamentally the same software architecture. The rest of this document applies to all system components unless otherwise noted.

    hashtag
    Operating System

    The system uses Debianarrow-up-right 12 as the base operating system. Debian is a free and open source Linux distribution developed by the Debian Project. The operating system is first installed with the minimally required dependencies and then any additional packages required by the system are installed during build time.

    Due to the extensive security measures, users are limited to using the application software and will not have access to Debian's typical set of features.

    hashtag
    Application Architecture

    All machines are completely disconnected from any network and have network capabilities disabled, but the frameworks and architecture employed are borrowed from web-based development. The user interacts with a restricted browser which communicates with a server that provides the web-content and another server that provides application data and hardware status.

    hashtag
    kiosk-browser

    kiosk-browser is a web browser restricted to rendering a single full-screen application. The code can be found in the . It is a thin application which uses as its rendering engine. The browser communicates with the frontend server which serves HTML, JavaScript, and assets. The browser also communicates with the backend server which serves application data. Electron enables the browser to access certain operating system APIs - such as open file dialogs - that a lone renderer would not have access to. The browser is launched at startup, with limited privileges, and cannot be exited. Everything a standard (non-vendor) user sees or does is mediated through kiosk-browser.

    hashtag
    Application Frontend Server

    The frontend is a application served from a server. All code for the application frontends are in the under apps/[app-name]/frontend.

    hashtag
    Application Backend Server

    The application backend is a separate server which acts as the core of the entire application in that it manages all persistent data and communication with peripherals. All code for the application backends are in the under apps/[app-name]/backend. Most code is written in TypeScript but some performance sensitive code, such as interpretation and background daemons, are written in and executed as binaries at runtime.

    hashtag
    Application Data Management

    All application data that persists across restarts is stored or tracked in a database. Each machine has a single database that the application backend accesses to update or retrieve data such as election configuration, cast vote record data, diagnostic data, etc. Logging data is a notable exception that is stored outside of the application databases.

    hashtag
    Peripheral Management

    The hardware peripherals are polled and managed through the application backends. For example when detecting the status of the card reader, the browser polls the backend server which in turn polls the hardware itself and returns a status to the browser. In order to manage changing states of more complex hardware such as scanners, the backends use state machines.

    The exact layer between the application backend and the hardware varies by hardware. Some run in-process whereas others run as a separate process with which the backend communicates. For the accessibility peripherals - the accessible controller and the sip-and-puff interface - the backend starts and manages a daemon which surfaces user input directly to the browser as keyboard commands.

    In many cases VotingWorks has written custom drivers that interface directly with the USB device. In other cases, VotingWorks leverages open-source middleware layers installed as Debian packages:

    Machine
    Peripheral
    Middleware Source

    Firmware for embedded devices such as screens and speakers is bundled with the operating system.

    hashtag
    Software Independence

    The voting system achieves software independence through the use of independent voter-verifiable paper records. All ballots are voter-verified paper ballots, either or .

    On hand marked paper ballots, voters fill in bubbles next to their selections. Because voter indications are made and reviewed directly by the voter, they are inherently voter-verified. The software interprets the image of the ballot for tabulation but, of course, the paper ballot persists after scanning.

    For machine marked paper ballots, voters make selections on screen at VxMarkScan. After the voter has made all their selections, the ballot is printed and presented to the voter. The ballot displays a textual representation of the selections and a QR code with the selections encoded. The voter reviews the ballot and, once accepted, the voter-verified ballot is ejected into the attached ballot box. VxMarkScan's machine marked ballots are not actually tabulated until they are scanned at a scanner.

    Ballots are never modified by the system after voter verification in any way that could affect voter selections or the ability to perform an audit. The only modification to ballots is the possible use of an imprinter on VxCentralScan, which prints only an identifier along the outside margin of the ballot.

    Because all voter selections are recorded on paper, voter-verified, and unmodified, the election results can always be re-tabulated or audited.

    hashtag
    Key VotingWorks Repositories

    There are four code repositories relevant to the voting system:

    • — Core application code

    • — Generic Electron-based kiosk-mode browser

    • — Links compatible versions of vxsuite and kiosk-browser, and includes the scripts necessary to create a production machine

    hashtag
    Key Dependency Chart

    Dependency
    Version

    hashtag
    Traceability of Procured Software

    We take care to ensure that we're pulling authentic/correct versions of dependencies, by verifying against known hashes, checksums, or digital signatures. The details of this are covered in .

    hashtag
    Software Best Practices

    The VotingWorks codebase is written in TypeScript and Rust, two widely used languages with well established coding conventions. We make use of automatic code linters to enforce these conventions. Details about our best practices and tooling used to enforce those best practices can be found here:

    We also require peer code review of every change (), and for larger changes and features, we hold architecture discussions as a team to land on the best possible solutions given the constraints.

    Our practices around testing are covered under .

    hashtag
    Failure Recovery

    The VotingWorks codebase uses database transactions to ensure that only complete and consistent (and not partial) updates are persisted. For data synced across a machine's internal drive and a connected USB drive, namely CVRs, we detect when data has fallen out of sync after a failure using the Merkle tree hash of the data () and re-sync data as needed.

    circle-check

    Through the above best practices, tooling used to enforce those best practices, and peer code review of every change, we guarantee that we meet the following requirements:

    • 2.3: Voting system logic is clear, meaningful, and well-structured

    hashtag
    Common Software Functions

    Subsequent articles will describe the particular software design of each application, but some software patterns are common across all applications and described here.

    hashtag
    USB Management

    All VxSuite components require a USB drive at some point in their operation for configuration or for the import or export of results. The application is polling for attached USB drives multiple times per second. If a USB drive with a FAT32 partition is detected, the application will attempt to mount the USB drive to a known mount point. Once mounted, the USB drive will be available for use by the application.

    The USB drive should be ejected before removing it. Most critical operations also make sure to sync the data to the USB drive before allowing the user to continue, however, so removing the USB drive without ejecting will normally not result in problems.

    Only one USB drive can be used at a time and additional USB drives inserted after the first USB drive will be ignored.

    hashtag
    Document Creation

    All VxSuite components must generate documents for printing or export. VxAdmin and VxScan must generate tally and ballot count reports. All components must generate diagnostic readiness reports.

    In order to do so, the applications have a headless browser (specifically Chromium) launched by the backend. Exported documents are all defined in terms of HTML (using React), so the headless browser is able to load the documents and render them as PDFs. The PDFs can then be sent to printer or saved to a USB drive.

    hashtag
    Date & Time Management

    The date and time is set on the machine in during initial configuration before the machine is sent to a customer. There is some amount of "clock drift" over time for all computers, however, so eventually the clocks may be wrong. This may cause problems with authentication due to mismatched timestamps and will cause reports to have incorrect timestamps.

    All machines allow system administrators and election managers to edit the date, time, and time zone in order to address clock drift or, in rare cases, to set up machines for use in a part of the jurisdiction with different time settings.

    circle-info

    User Manual Reference:

    hashtag
    Other Shared Software Patterns

    VxAdmin Function

    VxAdmin acts as the election setup hub at the beginning of the election and the results aggregation and reporting hub at the end of an election (and also at the end of testing).

    hashtag
    Configuration and Election Packages

    Only a can authenticate onto an unconfigured VxAdmin and configure it with an election package from an external system. The election package must be loaded via a USB drive. The election package must be a valid .zip . If the election package zip file, election definition file, system settings file, or metadata file are not valid, VxAdmin will surface an error to the user.

    https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/java_card.tsarrow-up-right
    https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/certs.tsarrow-up-right
    https://github.com/votingworks/vxsuite/blob/v4.0.2/libs/auth/src/cryptography.tsarrow-up-right
    https://github.com/votingworks/vxsuite-complete-system/blob/v4.0.2/config/vendor-functions/basic-configuration.sharrow-up-right
    https://github.com/votingworks/vxsuite/tree/v4.0.2/libs/auth#scriptsarrow-up-right
    https://github.com/votingworks/openfips201arrow-up-right

    VxMarkScan

    Accessible controller

    VotingWorks

    VxMarkScan

    PAT (sip and puff)

    VotingWorks

    VxAdmin

    Printer

    VxCentralScan

    Scanner

    vxsuite-build-systemarrow-up-right — Our framework for building VxSuite and managing its dependencies, across versions and environments

    Rust Packages

    See the relevant

    yarn

    1.22.22

    Electron

    36.4.0

    Chromium

    Kiosk Browser Node Packages

    See the relevant

    2.4: Voting system structure is modular, scalable, and robust
  • 2.5: The voting system supports system processes and data with integrity

  • 2.6: The voting system handles errors robustly and gracefully recovers from failure

  • Much of 2.5 is additionally covered under System Integrity.

    All

    Card reader

    PCSC litearrow-up-right

    VxScan

    Scanner

    VotingWorks

    VxScan

    Printer

    VotingWorks

    VxMarkScan

    Printer-scanner

    Debian

    12.11

    Additional Debian Packages

    See build system package inventoryarrow-up-right

    Node.js

    20.16.0

    pnpm

    8.15.5

    Application Node Packages

    See the relevant lock filearrow-up-right

    Rust

    1.86

    kiosk-browser repositoryarrow-up-right
    Electronarrow-up-right
    Chromiumarrow-up-right
    Reactarrow-up-right
    Node.jsarrow-up-right
    vxsuite repositoryarrow-up-right
    Node.jsarrow-up-right
    vxsuite repositoryarrow-up-right
    Rustarrow-up-right
    SQLitearrow-up-right
    hand marked ballots
    machine marked ballots
    vxsuitearrow-up-right
    kiosk-browserarrow-up-right
    vxsuite-complete-systemarrow-up-right
    Hash/Checksum Verification of Dependencies
    TypeScript best practices and toolingarrow-up-right
    Rust best practices and toolingarrow-up-right
    examples of that process herearrow-up-right
    Hashing of Continuously Exported Cast Vote Records
    Logging
    Diagnostics
    Application architecture diagram
    Quality Assurance Protocols – Software

    VotingWorks

    Once VxAdmin is configured, system administrators and election managers can export signed election packages. The exported election package is the same as the imported election package but is accompanied by a digital signature, which ensures that the election package was validated by a certified VxAdmin. The election packages loaded into VxMarkScan, VxScan, and VxCentralScan must be signed and unsigned election packages will be rejected.
    circle-info

    User Manual References: &

    hashtag
    Smart Card Management

    Smart cards are used for two-factor authentication on all machines in the system. They can only be programmed at VxAdmin with system administrator privileges.

    Programming, like authentication, takes place via the laptop's built-in USB card reader. Once a card is inserted, the application is able to detect the card and read and write data by issuing APDUs (application protocol data units) which are the standard form of communication between smart card readers and smart cards.

    For extensive details on the authentication scheme, see the access control documentation.

    circle-info

    User Manual Reference:

    hashtag
    USB Formatting

    VxSuite components require USB drives to be formatted with a FAT32 partition. The majority of USB drives are sold pre-formatted as FAT32, but some come in other formats. If an improperly formatted USB drive is inserted into a VxSuite component, it will be treated as if there is no USB drive.

    VxAdmin includes a utility to format USB drives to be compatible with the system. The utility is available only to system administrators. It will rewrite the partition table on the drive to include a single partition with a FAT32 formatted filesystem that takes up all available space on the drive. The reformatting clears the USB drive and is thus a destructive action. If a USB drive is already correctly formatted, the feature can be used to clear its data. VxAdmin applies a new label to the reformatted USB drive in the form of VxUSB-00000, where the 0's can be any random alphanumeric characters.

    Improperly formatted USB drives can only be detected and reformatted if there is some partition already existing, so a USB drive without any partitions cannot be reformatted using VxAdmin.

    circle-info

    User Manual Reference:

    hashtag
    CVR Management

    The core post-election (and pre-election testing) function of VxAdmin is loading, managing, and tallying cast vote records (CVRs).

    hashtag
    Loading CVRs

    CVRs must be loaded from a USB drive. CVRs are exported from VxScan or VxCentralScan and are accompanied by a digital signature. CVRs without a digital signature cannot be loaded. CVR exports with digital signatures that do not match the content of the CVR exports cannot be loaded in order to prevent tampering.

    The CVRs from the scanners are saved to specific directory structure on the USB drive, but exports can be loaded from anywhere on a USB drive's filesystem. When selecting an export manually, the export's metadata.json file must be selected by the user.

    When loading a full CVR export, each CVR is loaded into VxAdmin's backend store as one cvrs record. The CVR record includes a data blob representing the votes as interpreted by the scanner, a data blob representing the mark scores for all bubbles on the ballot (if a hand-marked paper ballot), and a series of metadata fields: ballot style, voting method (absentee vs. precinct), batch, scanner, precinct, sheet number within a multi-sheet ballot, and flags for adjudication reasons such as overvotes, undervotes, write-ins, or fully blank ballots. The metadata fields are used later on for filtering or aggregating tallies or ballot counts into groups.

    Each write-in on a CVR will map to a write-ins record, whether it is an unmarked write-in or a proper write-in. The ballot images are also each saved as database records. The write-in record links the write-in to its respective CVR, to the ballot images, and eventually to its adjudication result. The write-in adjudication interface essentially iterates through all write-ins records on a per contest basis.

    If an error is found when loading any single CVR in a CVR export, the entire export is rejected and a message is surfaced to the user. CVRs can be rejected for a variety of reasons: authentication failed; a file is incorrectly formatted; a CVR is not for a currently valid election, precinct, ballot style, or contest; a CVR with an identical ID has been loaded with different data. In everyday use of the system, all of these errors are either rare or impossible because VxAdmin will not allow loading CVR files from elections with mismatched metadata.

    VxAdmin allows loading CVR exports that have already been partially loaded. For example, imagine that VxCentralScan exports CVRs after scanning 5 ballots and then again after scanning 10 ballots. If we first load the 5 CVR export and then the 10 CVR export, the 10 CVR export will successfully load but will ignore the CVRs that have already been imported.

    circle-info

    User Manual Reference:

    hashtag
    Ballot Mode

    VxAdmin is always in one of three ballot modes:

    • Unlocked Ballot Mode - no CVRs have been loaded

    • Test Ballot Mode - test CVRs have been loaded

    • Official Ballot Mode - official CVRs have been loaded

    On VxAdmin, the ballot mode is determined by the ballot mode of the imported CVRs. VxAdmin differs in that respect from VxMarkScan, VxScan, and VxCentralScan, where the ballot mode is set directly by the election manager.

    Once VxAdmin is in test ballot mode, only test CVRs can be subsequently loaded. Similarly once VxAdmin is in official ballot mode, only official CVRs can be subsequently loaded.

    hashtag
    Removing CVRs

    CVRs can be removed by the user before results are marked as official or can be removed by fully unconfiguring VxAdmin. All CVRs are removed at once. The CVR data in the database along with all its dependent data - write-ins, ballot images, and adjudications - are permanently and irrecoverably deleted from the data store.

    hashtag
    Adjudication

    The tally reports from VxScan do not reflect any post-voting adjudication. All write-ins are simply "Write-In", unmarked write-ins are undervotes, and marginal marks are also undervotes.

    VxAdmin allows election managers to perform on-screen adjudication for ballots with write-ins, marginal marks, overvotes, or undervotes. Each contest (e.g. Mayor) is adjudicated individually. The election manager works through the queue of ballots for that contest.

    By default, only ballots with write-ins appear in the queue. If MarginalMark , Overvote, or Undervote is included in the system settings as part of the list of adminAdjudicationReasons , ballots with any of the specified features will also appear in the queue. A marginal mark is defined as any mark over a bubble which has a score of at least the marginal threshold defined in the system settings but less than the definite threshold defined in the system settings. When adjudicating ballots for a mix of adjudication reasons, the ballots appear in the following order within each contest:

    1. Ballots with overvotes

    2. Ballots with write-ins

    3. Ballots with both write-ins and marginal marks

    4. Ballots with marginal marks

    5. Ballots with undervotes

    The side of the ballot that the contest appears on is rendered to the user, with options to zoom out to the full ballot and back in again. When adjudicating a write-in, the write-in is further zoomed in. The location of the highlights are taken from the interpreted ballot layout, which is included in the cast vote record and loaded into VxAdmin alongside the ballot image.

    The user can adjudicate any contest option from marked to unmarked or vice versa. When presented with a marginal mark, the user can choose to leave it as an undervote or adjudicate it as marked. Write-ins can be adjudicated in one of three ways:

    • Official Candidate: the user can select an official candidate from the list

    • Unofficial Candidates: the user can select an unofficial write-in candidate from the list or add a new unofficial write-in candidate

    • Undervote: the write-in can be deemed invalid, after which it will be considered as an undervote in tallies

    As the user makes changes, captions are used to indicate differences between the original interpreted values and the new adjudicated values. Once the user is done adjudicating a ballot, they save their changes and continue in the queue.

    Changes made in adjudication are immediately reflected in tally reports.

    hashtag
    Unofficial Write-In Candidates

    The list of unofficial write-in candidates is created by the election manager as they adjudicate. The interface has an option to add a new write-in candidate and specify their name. That candidate will then be an option for other write-ins for the same contest. If there are no longer any adjudications that reference the unofficial candidates, their name will be removed from the list.

    circle-info

    User Manual Reference:

    hashtag
    Manual Tallies

    VxAdmin offers a way to enter manual tallies that are then added to reports. When manual tallies are present in a results export, they are always displayed separately from scanned tallies so that users can easily recognize the impact of manual results and recognize any human errors. The only exception to this rule is the CDF election results export in which, due to the limitations of the CDF, the manual and scanned tallies are simply combined.

    The ballot style, precinct, and voting method (absentee vs. precinct) must be specified before entering manual tallies. By associating manual tallies with these pieces of metadata, they can be filtered and grouped according to those dimensions when creating reports. Notably, manual tallies are not associated with a batch or a scanner like CVRs. When filtering on batch or scanner, manual tallies are excluded. When grouping by batch or scanner, manual tallies are treated as a single batch or scanner.

    The manual tallies for each contest are validated according to a standard formula:

    The same formula also applies to all results generated from scanned ballots. If a vote for three contest is overvoted, it is considered three overvotes. If the contest tallies entered by the user are incomplete or invalid, the user is presented with warning messages.

    In most cases, the ballot count will be the same across all contests. In some jurisdictions it is possible for different contests to have different ballot counts if, for example, someone votes on a ballot without local contests. In these cases, the user can override the ballot count on an individual contest basis.

    Unofficial write-in candidates can also be allocated votes in manual tallies and new unofficial write-in candidates can be added directly from the manual tallies interface.

    circle-info

    User Manual Reference:

    hashtag
    Tallying & Reports

    hashtag
    Vote Tallying

    Vote tallying is a multi-step process which takes place on the VxAdmin backend:

    Every tally is specified by a set of filters and groupings. The filter defines which CVRs are excluded and included. For example, a filter might limit the CVRs to the CVRs for a specific precinct. The group determines how tallies are subdivided by CVR metadata. For example, there may be a grouping on precinct which generates tallies for each precinct separately. Groups enable multiple related tallies to be efficiently generated at once.

    Filters and groupings are specified by the user directly with the tally report builder or implicitly with built-in reports.

    hashtag
    Group Determination

    If there are no groupings specified, there is only one set of tallies. If the precinct grouping is specified, there will be tallies for each precinct. If multiple groupings are specified, the possible resulting groupings need to be calculated. For example, if the precinct and ballot style groupings are both specified, only some combinations are possible because not all ballot styles exist in all precincts. If filters are specified, they may rule out certain groupings. For example, if the precinct grouping is specified but only Precinct A and Precinct B are included by the filter, then the Precinct C grouping will be excluded.

    If batch or scanner parameters are included, then VxAdmin will not attempt to compute the possible groupings because they may be too numerous. The potential groups will be created opportunistically during tallying.

    The purpose of computing the groups when possible, rather than always creating groups opportunistically, is to know which zero tallies to expect. When we group by precinct, we'd like to generate empty results for Precinct A even if no ballots for Precinct A were cast.

    CVR Aggregation

    The CVRs are pulled from the data store one by one and their vote data is added into an ongoing tally of ballots, contest option votes, overvotes, and undervotes. If the tallies are being grouped, the CVR will be added into the group that matches its metadata e.g. a CVR from a Precinct A ballot will be added to the Precinct A group.

    At this step in the process, the data does not contain any of the adjudication details from write-in adjudication.

    CVR aggregation is the most computationally expensive step in the vote tallying so the results are cached. The cache is reset anytime a CVR file is added or removed or anytime a vote is adjudicated through write-in adjudication.

    Write-In Adjudication Aggregation

    The write-in adjudication records are summarized from the data store and their adjudication statuses are added into an ongoing tally of write-ins for official candidates, write-ins for unofficial candidates, invalid write-ins, and unadjudicated write-ins. They are filtered and grouped according to the same parameters as the CVRs.

    circle-info

    The write-in adjudication report is simply the results of the write-in adjudication aggregation step, without filter or group, formatted into a PDF.

    hashtag
    Write-In Adjudication Hydration

    The vote tallies from the CVRs are then hydrated with the aggregated write-in adjudication tallies to create vote tallies that include the results of write-in adjudication. Before hydration, the tallies represent all write-ins as generic write-ins. The counts for generic write-ins are reconciled to counts for specific official and unofficial candidates.

    hashtag
    Manual Tallies Aggregation

    Manual tallies are already aggregated in the sense that each can represent more than one ballot. Since they are divided by ballot style, precinct, and voting method, however, they may need to be merged to match the groupings (or lack thereof) of the scanned vote tallies.

    hashtag
    Manual Tallies Hydration

    Manual tallies are then combined with the scanned tallies in one of two ways. For most reports, the manual tallies are paired with the scanned tallies but are not immediately added together. Reports can then display the manual and scanned tallies separately in addition to showing the total tallies. For the CDF election results report, however, the manual tallies and scanned tallies are added together because there is not a clear way to represent the difference between them in the CDF.

    Reporting

    The final step is for the VxAdmin backend to format the vote tallies into one of VxAdmin's Results Export Formats and export the result onto a USB drive or, if it is a PDF document, print it.

    circle-info

    User Manual Reference:

    hashtag
    Ballot Count Tallying

    Ballot counts are tallied as part of the vote tallying flow described above, but there is a separate tallying path that only calculates the ballot counts. It is used when generating ballot count reports and exports from VxAdmin. It follows the same steps as vote tallying, but is more efficient because it can use the underlying SQLite database to generate tallies rather than iterating through each CVR one-by-one.

    hashtag
    Ballot Count Definition

    When tallying ballot counts, VxAdmin is actually tallying sheet counts. In an election where all ballots are a single sheet, there is no distinction between ballot counts and sheet counts. In an election with multi-sheet ballots, there may be different numbers of different ballot sheets. VxAdmin tallies each sheet separately, which is displayed on tally reports and ballot count reports.

    The Ballot Count is defined in VxSuite as simply the count of first sheets. For example, if there are 1,000 first sheets and 999 second sheets, the ballot count will appear in reports as 1,000.

    hashtag
    Official vs. Unofficial Results

    Results on VxAdmin are considered unofficial until the election manager marks them as official. As long as results are unofficial, CVRs can be loaded, write-ins can be adjudicated, and manual tallies can be added and edited. All reports and result exports are labelled as "Unofficial."

    Once the results are final and often only after a jurisdiction's specific certification process, the election manager can mark results as official. All reports and result exports will then be labelled as "Official." CVRs can no longer be loaded, write-ins can no longer be adjudicated, and manual tallies can no longer be altered.

    There are two ways to exit official results mode without unconfiguring VxAdmin:

    • The system administrator can revert election results back to unofficial, which leaves all election data intact but allows it to be altered again by an election manager

    • The election manager may remove all election data at once, which would require restarting aggregation and adjudication from scratch

    hashtag
    Printer Management

    VxAdmin can print reports via an attached printer. The supported printer is the HP LaserJet Pro 4001dn. VxAdmin can also export reports as PDFs so, in the event of a printer failure, reports will always be available.

    VxAdmin interfaces with the printer through the CUPS, the open-source printing system developed by Apple and installed on our Debian system. When a printer is attached, it is registered with the CUPS server and made available to the application. VxAdmin is able to send print jobs to the printer via CUPS commands. The HP LaserJetPro does not require any additional third-party or in-house driver because it supports the IPP (Internet Printing Protocol) which CUPS then utilizes.

    Using IPP, the VxAdmin is also able to poll the detailed status (toner level, jam status, etc.) of the printer for use in the diagnostics interface.

    VxAdmin can only connect with one printer at a time and will always connect with with the first attached printer.

    system administrator
    Election Package
    total ballots∗votes allowed in contest=total votes+total undervotes+total overvotes\text{total ballots} * \text{votes allowed in contest} = \text{total votes} + \text{total undervotes} + \text{total overvotes}total ballots∗votes allowed in contest=total votes+total undervotes+total overvotes

    Cast Vote Records

    A cast vote record is a record of voter selections based on the system's interpretation of a scanned ballot. Each cast vote record corresponds to a single scanned ballot sheet. Multi-sheet ballots produce multiple cast vote records.

    Cast vote records are exported from VxScan and VxCentralScan onto USB drives and then imported into VxAdmin. Each cast vote record export is created with a digital signature. VxAdmin verifies this signature when importing cast vote records to ensure that the export has not been tampered with.

    hashtag
    Directory Structure

    In order to export cast vote records efficiently and without compromising voter privacy, every cast vote record is generated individually. The structure of a cast vote record directory is as follows:

    The cast vote record export contains a directory for each cast vote record, labelled with its UUID. Each specific cast vote record directory contains:

    • Cast Vote Record Report - Contains information about the election and the ballot interpretation in the Common Data Format. The information in the report is used as the basis for tabulation by VxAdmin.

    • Images - Ballot images to be used in adjudication or auditing. Included for all ballots.

    • Interpreted Ballot Layouts - Metadata for the position of ballot features such as contests, contest options, and bubbles in the ballot image. The interpreted layout data is used to properly crop and highlight ballot images for adjudication. Included for hand marked ballots but not machine marked ballots.

    In addition, there is a metadata file that applies to the entire export at the root of the directory, metadata.json.

    hashtag
    CVR UUIDs

    The v4 UUID (universally unique identifier) for each cast vote record is generated when the ballot information is first stored in the database in VxScan or VxCentralScan. It is generated with the node package uuid which uses the system's underlying FIPS-complaint OpenSSL implementation to generated random bytes.

    hashtag
    Rejected Ballots

    Images of rejected ballots are also included in the cast vote record export. There are no layout files or cast vote record report for rejected ballots because they are often uninterpretable. Rejected ballots will appear in the directory with the prefix rejected-, as in the following example:

    hashtag
    Cast Vote Record Report

    hashtag
    CDF Implementation

    VxSuite does not use any data extensions beyond the NIST specification, but some fields are made required that are not required in the original NIST specification. The two specifications can be compared by comparing the with the . The additionally required fields are listed in a table below.

    Because VxAdmin requires a VxSuite digital signature on all imported cast vote records, it's not possible to import a cast vote record from outside of VxSuite. The goal of using CDF is to help external systems consume VxSuite cast vote records for audit or analysis.

    hashtag
    VxSuite Required Fields

    CDF Class
    Additionally Required Attributes

    hashtag
    Report Metadata

    The CDF specification includes many metadata fields that might help a consumer make sense of the cast vote record data. For example, you may define the candidates that are referenced as contest selections. VxSuite cast vote records all include this metadata to conform to the CDF, but nearly none of it is actually utilized when imported into VxAdmin. VxAdmin already has that information from the . The only data that is utilized by VxAdmin is the GeneratedDate and the indication of whether or not the report is a test report in ReportType and OtherReportType.

    hashtag
    CastVoteRecordReport

    CDF Attribute
    Usage

    hashtag
    CastVoteRecordReport.ReportingDevices

    Only one ReportingDevice is ever listed:

    CDF Attribute
    Usage

    hashtag
    CastVoteRecordReport.Party

    The list of parties in the cast vote record report is mapped directly from the list in the election definition:

    CDF Attribute
    Usage

    hashtag
    CastVoteRecordReport.GpUnit

    GpUnits are created for each in the election, for the , and for the state:

    CDF Attribute
    Usage

    hashtag
    CastVoteRecordReport.Election

    The Election class has values mapped to it directly from the :

    CDF Attribute
    Usage

    hashtag
    Cast Vote Record Attributes

    Each cast vote record includes a set of ballot metadata attributes:

    CDF Attribute
    Usage

    hashtag
    Ballot Images

    The CVR.BallotImage attribute contains information about the images accompanying the cast vote record. It always contains information for both the front and back images of the ballot. Its attributes are as follows:

    CDF Attribute
    Usage

    Hashes of the ballot image and ballot layout files are included in the cast vote record report so that the hash (and digital signature) of the cast vote record export will reflect any change to the image or layout files.

    hashtag
    Snapshots

    The CDF specification allows detailing multiple versions of the same cast vote record as "snapshots."

    For hand marked paper ballots, there are both "original" and "modified" snapshots. The "original" snapshot contains mark thresholds for every single bubble on the ballot. The "modified" snapshot contains only the marks that were detected as definite marks and counted as valid or invalid votes.

    For machine marked ballots, there is only an "original" snapshot.

    The snapshot is referenced in the CVR.CurrentSnapshotId field by it's identifier, which will be the unique identifier of the cast vote record along with its type, such as

    hashtag
    Ballot Type

    The CDF specification does not have any allowance for a ballot type such as "absentee" or "precinct" at the metadata level, so it is added as information to each snapshot:

    CDF Attribute
    Usage

    hashtag
    Representing Votes

    The CVRContest class within each snapshot contains a list of vote records by contest. The fields are used as follows:

    CDF Attribute
    Usage

    hashtag
    Ballot Images

    Ballot images are .jpg files. They are included in the cast vote record in order to be used for adjudication and auditing. Ballot images are generated by the scanning hardware and then normalized to reduce skew and enforce a consistent orientation. All images are persisted in black and white to reduce disk space usage.

    hashtag
    Ballot Layouts

    Ballot layouts are JSON files which describe the discovered position of ballot content within interpreted ballots, including where each contest and contest option appears. Although the layout of ballot content within the ballot grid is specified by the election definition, the ballot content may be positioned in a slightly differently location in each scanned ballot image due to offset or skew of the ballot during scanning. As a result, the layouts are included in order to have accurate image highlights and crops for adjudication.

    hashtag
    Export Metadata

    The metadata file includes data that applies to all cast vote records in the export. There is only one per export. The relevant attributes are:

    Attribute
    Usage

    hashtag
    Batch Manifest

    Each cast vote record is associated with a batch via its BatchId metadata field. The CDF doesn't have a place within the cast vote record report to include batch metadata, so it is included here.

    Attribute
    Usage

    VxScan Hardware

    hashtag
    Overview

    VxScan consists of two main components - the collapsible ballot box and the scanner itself - which are secured together during setup.

    hashtag

    Contest.Name

    The contest title

    CandidateContest.VotesAllowed

    The contest's number of seats

    CandidateContest.PrimaryPartyId

    The party identifier of the associated party, if a primary contest

    CandidateSelection.@id

    The candidate identifier from the election definition

    CandidateSelection.CandidateIds

    The candidate identifier from the election definition

    CandidateSelection.IsWriteIn

    Whether the selection represents a write-in bubble

    BallotMeasureSelection.@id

    The option identifier from the election definition

    BallotMeasureSelection.Selection

    The option label that appeared on the ballot

    PartyIds

    The party identifier from the election definition, if for a primary ballot

    UniqueId

    The UUID for the ballot generated by the scanner

    BatchSequenceId

    When using VxCentralScan, contains the index of the sheet within the batch. 1-indexed.

    BallotAuditId

    When using an imprinter on VxCentralScan, contains the UUID imprinted on the ballot

    CVRContestSelection.OptionPosition

    The index of the contest position within the contest

    CVRContestSelection.Status

    The list of applicable contest selection statuses:

    • "invalidated-rules" - mark is part of an overvote

    • "needs-adjudication" - mark corresponds to a write-in

    SelectionPosition.HasIndication

    "yes" or "no" depending on whether a mark in the bubble passed the mark threshold. In the original hand marked paper ballot snapshots, this may be either value. In the modified snapshot, it is always "yes" except for unmarked write-ins.

    SelectionPosition.NumberVotes

    Fixed to 1

    SelectionPosition.IsAllocable

    "yes" except:

    • "no" if an overvote

    • "unknown" if an unmarked write-in

    SelectionPosition.MarkMetricValue

    The mark score, a decimal between 0 and 1.00 such as 0.23. Only included in the original snapshots.

    SelectionPosition.Status

    • "invalidated-rules" if an overvote

    • "needs-adjudication" if an unmarked write-in

    SelectionPosition.OtherStatus

    "unmarked-write-in" if an unmarked write-in

    CVRWriteIn.WriteInImage

    The BallotImage data for the side of the sheet on which the write-in occurs

    The serial number of the scanner

    CVR

    BallotStyleId, BallotStyleUnitId, BatchId, CreatingDeviceId, UniqueId

    CVRContest

    CVRContestSelection

    CVRContestSelection

    • ContestSelectionId

    • SelectionPosition is limited to length 1

    CVRSnapshot

    CVRContest

    Version

    Fixed to "1.0.0"

    ReportType

    Always includes "originating-device-export". If a test report, also includes "other"

    OtherReportType

    If a test report, "test", otherwise undefined

    GeneratedDate

    The generated date in Date Time String Formatarrow-up-right

    ReportGeneratingDeviceIds

    The scanner serial number

    @id

    The scanner serial number

    SerialNumber

    The scanner serial number

    Manufacturer

    Fixed to "VotingWorks"

    @id

    The party identifier from the election definition

    Name

    The full name of the party, e.g. "Democratic Party"

    Abbreviation

    The abbreviation of the party, e.g. "R"

    @id

    • Precinct: The precinct identifier from the election definition

    • County: Fixed to "election-county"

    • State: Fixed to "election-state"

    Type

    • Precinct: "precinct"

    • County or State: "other"

    Name

    The precinct, county, or state name

    @id

    The election's ballot hash

    Name

    The title of the election

    ElectionScopeId

    Fixed to "election-state"

    Candidate.@id

    The candidate identifier from the election definition

    Candidate.Name

    The candidate name

    Contest.@id

    The contest identifier from the election definition

    BallotSheetId

    The index of the sheet within the ballot. For the second sheet of a multi-sheet ballot, it would be 2

    BallotStyleId

    The ballot style identifier from the election definition

    BallotStyleUnitId

    The precinct identifier from the election definition

    Batch

    The batch identifier

    CreatingDeviceId

    The scanner serial number

    ElectionId

    The election's ballot hash

    Location

    Location of the image file relative to the report, such as:

    Hash.Type

    Fixed to "sha-256"

    Hash.Value

    • Images & Layouts: {SHA256 hash of image}-{SHA256 hash of layout}

    • Images Only: SHA256 hash of image

    CVRSnapshot.Status

    Fixed to ["other"]

    CVRSnapshot.OtherStatus

    JSON blob representing the ballot type. The possible values are "absentee", "precinct", or "provisional".

    CVRContest.ContestId

    The contest identifier from the election definition

    CVRContest.Overvotes

    The number of overvotes for a contest. The number can only be 0 or the maximum number of votes in the contest

    CVRContest.Undervotes

    The number of undervotes for a contest

    CVRContest.WriteIns

    The number of write-ins for a contest

    CVRContest.Status

    The list of applicable contest statuses:

    • "not-indicated" - no votes cast in contest

    • "undervoted" - fewer than allowed votes cast in contest

    • "overvoted" - more than allowed votes cast in contest

    • "invalidated-rules" - applies if overvoted

    CVRContestSelection.ContestSelectionId

    The option identifier from the election definition

    arePollsClosed

    For VxScan exports, the flag indicates whether polls where closed at the time of export. If polls were not closed, that may indicate an incomplete export

    castVoteRecordReportMetadata

    The cast vote record report without any specific cast vote record data. In other words, only data about the election and its contests

    castVoteRecordRootHash

    A hash of all cast vote record files in the export. Including the hash here, which rolls up into the digital signature, ensures that cast vote records cannot be added or removed from the export

    batchManifest

    The list of batches on the originating scanner, see below

    id

    The UUID of the batch generated by the scanner

    label

    The label for the batch

    batchNumber

    The sequential number of the batch, e.g. 2 for the second batch

    startTime

    The time a batch was started in ISO 8601 format

    endTime

    The time a batch ended in ISO 8601 format

    sheetCount

    The number of sheets (i.e. cast vote records) in a batch

    NIST JSON schemaarrow-up-right
    VxSuite JSON schemaarrow-up-right
    election package
    Party
    Precinct
    County
    election definition

    scannerId

    - root
        - metadata.json
        - 0cfaa953-11fa-4483-af03-04eed1d8cc6f
            - cast-vote-record-report.json
            - 0cfaa953-11fa-4483-af03-04eed1d8cc6f-front.jpg
            - 0cfaa953-11fa-4483-af03-04eed1d8cc6f-front.layout.json
            - 0cfaa953-11fa-4483-af03-04eed1d8cc6f-back.jpg
            - 0cfaa953-11fa-4483-af03-04eed1d8cc6f-back.layout.json
        - 0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c
            - cast-vote-record-report.json 
            - 0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c-front.jpg
            - 0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c-front.layout.json
            - 0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c-back.jpg
            - 0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c-back.layout.json
        - ...
        - ...
        - ...
    - root
        - ...
        - rejected-0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c
            - 0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c-front.jpg
            - 0cfbf789-d8a0-4d3f-a221-b7fe8e0bb47c-back.jpg
        - ...
    file:864a2854-ee26-4223-8097-9633b7bed096-front.jpg
    864a2854-ee26-4223-8097-9633b7bed096-modified
    {
      ballotType: "absentee"
    }
    Ballot Box
    Ballot box front, collapsed
    Ballot box side, collapsed
    Ballot box lid underside, collapsed

    The ballot box features a telescoping handle and wheels for ease of transport. When collapsed, closing straps run around the side of the box to hold it closed. Before the ballot box is set up, the closing straps are loosened and secured to the underside of the ballot box lid.

    The front of the ballot box is the ballot door, which is used to access the bin interior and any ballots within. It's opened by pulling the ballot door latch pictured above, which automatically latches whenever the door is closed. A seal can be installed to prevent the door from being opened without tamper-evidence.

    The ballot door has a built-in auxiliary bin for depositing ballots in situations where the ballots cannot be scanned. It can be in one of three states: closed, partially open for depositing ballots, or fully open for removing ballots. It's opened by pressing down on the indicated handle which can be sealed with the adjacent seal point.

    After closing straps are loosened, the ballot box can be expanded. An accented foot hook can be used as an aid in expanding the box. Once the box is fully expanded, the lid can be rotated up and over 270 degrees to eventually close and latch into place.

    Ballot box side, open
    Ballot box interior
    Ballot box side, closed

    After being latched, the ballot box lid can be released by pushing the ballot box lid handle, indicated below. The handle is covered by the scanner when installed, so it cannot be opened while the scanner is in operation and sealed in place. The box lid has a ballot slot which mates with the scanner's ballot outfeed.

    The scanner attaches to the ballot box by sliding into the area in the front of the lid. Flanges on the bottom of the scanner prevent it from moving up and down or side to side. To secure the scanner front to back and lock it into place, the scanner has a security bolt which mates with the security bolt hole on the top of the ballot box. After the security bolt is engaged, the scanner cannot be removed until the security bolt is unsealed and released. This is covered more fully in the next section.

    Ballot box from above, closed

    hashtag
    Scanner

    The scanner is built into a customized Pelican 1485 Air case. The COTS case features:

    • Seal Points

    • Carrying Handle

    • Spring-Loaded Latches

    Additional cuts are made into the case for the back power port, the back cable wrap, the security bolt exit, nameplate attachment, and mounting features within the case.

    Ballot box with scanner installed
    Scanner rear

    The case is opened by pressing the buttons on each case latch and then lifting the lid. The elements that a voter or poll worker interact with are generally accented in purple, just as with the ballot box. In the picture below you can see the smart card insert, security bolt, ballot infeed, and printer outfeed all accented in purple.

    Scanner main bottom tub
    Scanner upper tub

    When the scanner is first installed on the ballot box, the security bolt must be disengaged. While the security bolt is disengaged, the smart card slot will be blocked. Once the scanner is installed on the ballot box, the user must push the bolt down to lock the scanner into place on the ballot box. This will also unblock the smart card slot. In this way, the scanner can not be activated until it is properly installed.

    When the scanner must be removed from the ballot box, the user pushes the security bolt release to the left to disengage the security bolt. The security bolt release is accented with graphical instructions for the user. In order to access the security bolt release, the poll worker door must be opened, which also exposes the scanner's USB ports. The poll worker door can be sealed shut by passing a seal through a cutout in the door and the hole in the top of the security bolt.

    Poll worker door area
    Poll worker door sealed

    Poll workers will normally not have to interface with any parts of the scanner that have not already been described, but election managers may have to open the access door to perform maintenance on the printer and scanner. The access door is held in place by the poll worker door and can only be opened when the poll worker door is unsealed and opened. The printer and printer roll holder are beneath the access door toward the screen. The user presses the release lever on the right side of the printer to remove the printer roll holder and install a paper roll. The scanner can be opened simply by lifting the scanner cover handle, revealing the scanner glass for easy cleaning.

    Access door area
    Scanner features

    hashtag
    Scanner Internals

    The various components of the scanner are arranged and wired together within the Pelican case. Custom cut holes in the Pelican case allow mounting brackets in the top and bottom tubs which are then used to attach components.

    Power enters through a power module embedded in the case. The power module connects to a 24-volt power supply which supplies the scanner and printer with power. A 12-volt power supply is daisy-chained from the 24-volt power supply in order to power the single board computer.

    The metal chassis of the bottom tub is grounded to exterior ground via the power module. Everything else requiring grounding is then grounded to the bottom chassis - power supply, lid chassis, access panel, and the scanner.

    All USB cables ultimately connect to the single board computer. The card reader and printer connect via a custom USB cable directly to headers on the computer. The USB hub, which then connects to the USB ports and scanner, is connected directly to the computer. Finally, a USB-C cable connects the computer to the screen. The USB-C cable carries video, audio, touch input, and power. Audio is carried through the screen to the speakers via a separate cable.

    The wiring digram below outlines the power and data connections within the scanner. Black lines indicate power connections, gray lines indicate ground connections, and purple lines indicate data connections, which may also carry low voltage power.

    VxScan does not require any direct bodily contact or for the body to be part of any electrical circuit to function.

    VxScan Wiring Diagram
    Wiring components
    Voltage warning over power supplies

    To prevent access to internals, VotingWorks installs three seals over screws holding the metal panels in place - one on the bottom left panel covering the computer, one on the bottom right panel covering the power supplies, and one on the top panel holding the display in place. These seals are installed at the factory and are intended to be permanent aside from when panels need to be opened for repairs.

    Bottom left panel seal
    Bottom right panel seal
    Top panel seal

    hashtag
    Paper Path

    The paper path is carefully designed and tested to ensure a smooth and uninterrupted ballot scan and deposit. The voter inserts paper over the infeed which mates directly with the scanner. The scanner lid handle doubles as an upper deflector, deflecting ballots which are inserted too high by the voter. As the ballot passes through the scanner, it hits the ballot redirector behind the scanner. The ballot redirector is a logarithmic curve which ensures that wherever the ballot strikes, it will be directed downward. The ballot then passes through the outfeed slot (which is only open when the scanner case is open) into the ballot box.

    hashtag
    Audio Tactile Interface

    VxScan enables an audio tactile interface on all voter-facing screens when casting ballots. An accessible controller (Storm Interface Externally Mounted Audio Nav) is connected by an election worker to the second USB port behind the poll worker door. Headphones are plugged into the 3.5 mm (1/8 inch) stereo headphone jack available on the accessible controller. Voters may navigate, make selections, and adjust audio volume using the connected accesible controller.

    hashtag
    COTS Components

    VxScan includes many COTS components, which mostly fall into two categories. First, many small pieces of hardware such as fasteners are purchased commercially. These are called out in the bill of materials and are not generally critical components. Second, most of the electronic components are purchased commercially. Documentation for these components can be found in the documentation repositoryarrow-up-right.

    Manufacturer
    Component
    Mfr. Part Number
    Criticality

    Peripheral Dynamics, Inc.

    PageScan 6 Scanner

    PS6

    High

    USBFirewire

    10" USB A-B Cable

    RR-ADBU-10GR

    Medium

    L-com

    0.5m USB A-B Cable

    CAABLK-90RB-05M

    The specified neckloop achieves a T4 rating when used with assistive hearing devices that include T4 rated telecoils.

    hashtag
    Discussion of Critical Components

    As listed in the COTS table above, the high criticality components are as follows:

    • Aaeon UP Squared Pro 7000 Computer - As the computer which orchestrates ballot interpretation and vote tallying, the single board computer is a highly critical component. VotingWorks partners with Aaeon, Inc. and their production in Taiwan to ensure the trustworthy production and quality of each single board computer.

    • PageScan 6 Scanner - As the source of ballot images for interpretation, the embedded scanner is a highly critical component. Any interference in image creation could affect interpretation and subsequently vote tallies. Any interference in paper handling could affect ballot accounting. VotingWorks works closely with Peripheral Dynamics, Inc. to ensure the quality of the hardware and firmware of the scanner manufactured domestically. The specific VotingWorks firmware version is tracked by Peripheral Dynamics, Inc. and installed on all scanners.

    • Fujitsu Thermal Printer Mechanism and Control Board - The thermal printer is a less sensitive component than the previous two because it does not send sensitive data to the application - it only receives sensitive data. It is still a single-sourced component with complex subassemblies, however, and any issues printing would prevent jurisdictions from having accurate day-end results.

    • Solid State Drive - The solid state drive is the storage medium for all sensitive election data.

    The medium criticality components and the reasons for their classification are as follows:

    • USB Cables, Hub, and Mounts - USB cables connect to the computer and carry sensitive election data, so they are medium criticality. The attack vectors are difficult, however, and all cables can be produced by alternate manufacturers.

    • Power Cables & Power Supplies - Power supplies and cables can affect the reliability of the equipment in initially difficult to detect ways, and are thus medium criticality, but they generally cannot corrupt election data in a targeted or undetectable way.

    • Pelican Case - The Pelican case cannot meaningfully affect the operation of the software, but its sole supplier is Pelican. Since the equipment is designed around the particular case, the case and its supplier are considered critical.

    • Touchscreen - The Elo touchscreen is responsible for rendering election data and correctly handling user touches, but it generally cannot impact election data and impacts would be perceptible. It is custom component from a single manufacturer, however, and is certainly medium criticality.

    • Smart Card Reader - The smart card reader is responsible for communicating with smart cards to manage authentication, and is thus a critical component.

    • Audio Tactile Controller & Headphones - These components are required for use of the VxScan audio-tactile voting interface.

    CUPSarrow-up-right
    SANEarrow-up-right
    lock filearrow-up-right
    136.0.7103.149arrow-up-right
    lock filearrow-up-right

    VxSuite Election Definition

    The VxSuite Election Definition is a data format for defining an election that is specific to VxSuite. It is a JSON file which defines the essential features of an election - metadata, contests, parties, precincts, districts, ballot styles, candidates, and more. In addition to defining that basic structure of the election, the format contains translations for any text which may appear on the ballots and ballot layouts to map the bubbles on each ballot to contest options.

    hashtag
    Core Election Attributes and Relationships

    Election Entity Relationship Diagram

    hashtag
    Election

    The Election entity is the top-level entity that contains all other entities.

    Attribute
    Type
    Description

    hashtag
    Ballot Layout

    The ballot layout entity includes basic information about the physical ballots used for the election.

    Attribute
    Type
    Description

    The paperSize attribute accepts the following valid options:

    The metadataEncoding attribute must be "qr-code".

    hashtag
    Ballot Style

    Each ballot style corresponds to a single- or multi-sheet ballot. The contests on a ballot style are determined by its associated districts - every contest belonging to an associated district is considered a part of the ballot style. A ballot style may be used in multiple precincts, one ballot style might correspond to multiple ballot PDFs that have identical contest layouts but different precinct labels.

    Attribute
    Type
    Description

    hashtag
    OrderedCandidateOption

    Attribute
    Type
    Description

    A cross-party endorsed candidate may have multiple candidate options associated with the same id , but different partyIds.

    hashtag
    Contest

    There are two types of contests - candidate contests and yes-no contests. Both types share core attributes:

    Attribute
    Type
    Description

    hashtag
    Candidate Contest

    In a candidate contest, the voter makes a selection between pre-defined candidates or write-in options. The following attributes extend the shared attributes:

    Attribute
    Type
    Description

    hashtag
    Candidate

    Attribute
    Type
    Description

    hashtag
    Yes-No Contest

    In a yes-no contest, also known as a ballot measure, the voter makes a selection between two options. The following attributes extend the shared attributes:

    Attribute
    Type
    Description

    The description field supports rich text formatting, including images. Images are represented using the syntax <img src=\" + data URL + \">, where an image can be converted to a data URL using . For example, if an image after conversion via the aforementioned site yields the data URL data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO1n0X8AAAAASUVORK5CYII=, the image embedded in a yes-no contest description will look as follows:

    hashtag
    Yes-No Contest Option

    Attribute
    Type
    Description

    hashtag
    County

    One and only one county is associated with each election.

    Attribute
    Type
    Description

    hashtag
    District

    Districts are used to define levels at which a contest takes place. For example, an election may have districts defined for the state, county, town, and ward levels. Different contests can be associated with each of those levels.

    Attribute
    Type
    Description

    hashtag
    Party

    Parties are used in the data model either to associate candidates with a party, associate ballot styles with a party for a primary, associate contests with a party for a primary

    Attribute
    Type
    Description

    hashtag
    Precinct

    Attribute
    Type
    Description

    hashtag
    Precinct Split

    Attribute
    Type
    Description

    hashtag
    Ballot Strings

    The ballotStrings object contains the translations for any text which may appear on the ballot. The text falls into one of two categories: instructional text or election-specific text.

    hashtag
    Instructional Text

    Examples of instructional ballot text include:

    • "To vote, completely fill in the oval next to your choice."

    • "Vote for up to 3",

    • "Official Absentee Ballot"

    Although the system does not use the hand marked ballot instructional text for any purpose, it must be included in the election definition for security purposes. When included, it becomes a part of the and cannot be changed without invalidating older ballots.

    hashtag
    Election-Specific Text

    The core data model already includes names and labels. For example, the entity already has a name attribute. The names within the data model are used by default in the system in reports and administrative menus. The translations for all of these names are within the ballotStrings and are important for two main reasons:

    1. The language-specific strings are used to accommodate multi-lingual voting on VxMarkScan

    2. Including the translations in the election definition means they are included in the and cannot be changed without invalidating older ballots.

    The election-specific ballotStrings recognized by the system are the following:

    Description
    Key
    Value

    hashtag
    Example

    The language codes used are the for supported VxSuite languages: English, Spanish, Simplified Chinese, and Traditional Chinese.

    hashtag
    Grid Layouts

    Grid layouts describe where the bubbles and write-in areas exist on each ballot style. They must correspond exactly to the ballots used for the election in order for interpretation to succeed. For more information on the acceptable ballot format and its relationship to grid coordinates, see .

    gridLayouts is an array which contains entities with the following attributes:

    Attribute
    Type
    Description

    hashtag
    Outset

    The optionBoundsFromTargetMark field specifies an Outset entity. The purpose is to give the distance from the bubble to edges of the entire contest option e.g. the area that includes the bubble, the corresponding candidate's name, and some padding. The system uses this area during write-in-adjudication to highlight specific contest options for review.

    Attribute
    Type
    Description

    hashtag
    Grid Position

    Grid positions are defined positions on the ballot corresponding to bubbles that can be marked by a voter. The row and column coordinates of each grid position denote where the bubble is printed within the abstract "grid" created by the timing marks on the outer edges of the ballot. There are two types of positions - a standard option position corresponding to a candidate or option in the election definition or a write-in position corresponding to a write-in bubble and area on the ballot.

    hashtag
    Option Grid Position

    Attribute
    Type
    Description

    hashtag
    Write-In Grid Position

    Attribute
    Type
    Description

    In some jurisdictions, a write-in can only be counted if the associated bubble is filled in as for any other option. In other jurisdictions, a write-in must be counted even if the bubble is not filled. In order to detect these write-ins, a writeInArea is defined for each write-in grid position. The Rectangle specifies the area.

    hashtag
    Rectangle

    Attribute
    Type
    Description

    hashtag
    Examples

    Election definition examples are located in the vxsuite repository, such as .

    Medium

    GlobTek, Inc.

    USB-C Cable

    USBCW1M0USBC2SLEMBK

    Medium

    HID Omnikey

    Embedded Smart Card Reader

    R31210375-1

    Medium

    Aaeon

    Single-Board Computer

    UPN-ADLN97-A10-0864

    High

    ADATA

    Solid-State Drive

    IM2P32A8-128GCTB5

    High

    Tripp Lite

    USB Panel Mount

    U324-001-APM

    Medium

    CUI Devices

    Power Cable

    AC-C13 NA

    Low

    MEAN WELL

    12V Power Supply

    LRS-75-12

    Medium

    MEAN WELL

    24V Power Supply

    LRS-150-24

    Medium

    Fujitsu

    A4 Thermal Printer Mechanism

    FTP-68EMCL112-R

    High

    Fujitsu

    A4 Thermal Printer Control Board

    FTP-62EDSL201-R

    High

    Fujitsu

    A4 Thermal Printer Head Cable

    FTP-62EY001-R

    Medium

    Coolgear

    USB Hub

    CG-3510S4-BOARD

    Medium

    Pelican

    Outer Case

    Pelican Air 1485

    Medium

    Elo

    Touchscreen

    E976783

    Medium

    GoldenMate

    Uninterruptible Power Supply

    UPS 1000VA/600W

    Low

    Storm Interface

    Audio Tactile Interface Controller

    1406-33002

    Medium

    LORELEI

    Headphones

    X6

    Low

    Williams Audio Visual

    T-Coil Neckloop

    NKL-001

    Low

    gridLayouts

    array -

    county

    County metadata

    date

    string - YYYY-MM-DD

    Date of the election

    districts

    array -

    All districts

    id

    string

    Unique identifier

    parties

    array -

    All parties

    precincts

    array -

    All precincts

    seal

    string - SVG file format

    Seal for the election

    state

    string

    Name of the state

    title

    string

    Title of the election

    type

    string - "general" or "primary"

    Type of the election

    languages

    array - string

    Optional. The language codes for the languages covered by the ballot style

    orderedCandidatesByContest

    map <string, array - OrderedCandidateOption>

    Optional. A mapping from contest ID for candidate contests in the ballot style to an ordered list of candidate options that specify the ballot rotation order of candidates for this ballot style. If not specified, candidates will be listed in the order they are defined in the contest object.

    OrderedCandidateOption is specified in more detail in the table below.

    termDescription

    string

    Optional. Description of the term of the position, such as "For three years"

    Contest Option Labels

    contestOptionLabel

    key-value pairs, IDs mapped to labels

    Contest Terms

    contestTerm

    key-value pairs, IDs mapped to term descriptions

    Contest Titles

    contestTitle

    key-value pairs, IDs mapped to titles

    County Name

    countyName

    string

    District Names

    districtName

    key-value pairs, IDs mapped to names

    Election Date

    electionDate

    string

    Election Title

    electionTitle

    string

    Party Full Names

    partyFullName

    key-value pairs, IDs mapped to their full names

    Party Names

    partyName

    key-value pairs, IDs mapped to their short names

    Precinct Names

    precinctName

    key-value pairs, IDs mapped to names

    State Name

    stateName

    string

    row

    number

    Row position of the bubble in the timing mark grid

    contestId

    string - ID of

    Contest identifier

    optionId

    string - ID of or

    Option identifier

    row

    number

    Row position of the bubble in the timing mark grid

    contestId

    string - ID of

    Contest identifier

    writeInIndex

    number

    An index of the write-in position within the list of write-in positions for a contest (zero-indexed)

    writeInArea

    Area of the ballot to scan for a write-in

    ballotLayout

    Ballot Layout

    Physical ballot metadata

    ballotStrings

    array - Ballot Strings

    See Ballot Strings Section

    ballotStyles

    array - Ballot Style

    All ballot styles

    contests

    array - Contest

    All contests

    paperSize

    string

    Indicates physical length of the ballot

    metadataEncoding

    string

    Indicates how the ballot metadata will be encoded on the ballot

    id

    string

    Unique identifier

    precincts

    array - IDs for Precinct

    The IDs of all precincts which use the ballot style

    districts

    array - IDs for District

    The IDs of all districts whose contests are included in the ballot style

    partyId

    string - ID for Party

    Optional. The ID of the party to which the ballot belongs, if a primary

    id

    string

    Candidate ID

    partyIds

    array - string

    Endorsement party IDs for the giving bubble option.

    id

    string

    Unique identifier

    districtId

    string - ID for District

    The associated district of the contest such as a state, county, or ward

    title

    string

    Title of the contest

    type

    string - "candidate" or "yesno"

    Type of the contest

    seats

    number

    The number of selections a voter can make

    candidates

    array - Candidate

    Candidate options for the contest

    allowWriteIns

    boolean

    Whether the contest allows write-ins

    partyId

    string - ID for Party

    Optional. The ID of the party to which the contest belongs, if a primary

    id

    string

    Unique identifier

    name

    string

    Name as it appears on the ballot

    partyIds

    array - ID for Party

    Optional. The IDs of the parties associated with the candidate. The party name will appear next to the candidate

    description

    string

    Contest description

    yesOption

    Yes-No Contest Option

    "Yes" option

    noOption

    Yes-No Contest Option

    "No" option

    id

    string

    Unique identifier

    label

    string

    Label e.g. "Yes" or "No"

    id

    string

    Unique identifier

    name

    string

    Name e.g. "Choctaw County"

    id

    string

    Unique identifier

    name

    string

    Name e.g. "State of Mississippi"

    id

    string

    Unique identifier

    name

    string

    Short name which will appear on the ballot besides candidates e.g. "Republican"

    fullName

    string

    Full name which will appear in reports and in the titles of ballots e.g. "Democratic Party"

    abbrev

    string

    Abbreviation for a party e.g. "R"

    id

    string

    Unique identifier

    name

    string

    Name e.g. "Fire Station"

    districtIds

    array - ID for District

    Districts to which the precinct belongs. Not present if splits is specified, in which case distrit associations are specified per split.

    splits

    array - Precinct Split

    Splits within the precinct. Not present if districtIds is specified.

    id

    string

    Unique identifier

    name

    string

    Name e.g. "Precinct Split 1"

    districtIds

    array - ID for District

    Districts to which the precinct split belongs

    Ballot Language

    ballotLanguage

    string

    Ballot Style IDs

    ballotStyleId

    key-value pairs, Ballot Style IDs mapped to names

    Candidate Names

    candidateName

    key-value pairs, Candidate IDs mapped to names

    Contest Descriptions

    contestDescription

    key-value pairs, Contest IDs mapped to descriptions

    ballotStyleId

    string, ID for Ballot Style

    Identifies the ballot style

    optionBoundsFromTargetMark

    Outset

    Describes where the entire contest option area sits relative to the bubble

    gridPositions

    Grid Position

    Describes bubble and write-in positions on the ballot

    top

    number

    Distance from center of bubble to top of option bounds

    right

    number

    Distance from center of bubble to right of option bounds

    bottom

    number

    Distance from center of bubble to bottom of option bounds

    left

    number

    Distance between center of bubble to left of option bounds

    type

    string - "option"

    Indicates this is a standard option position

    sheetNumber

    number

    1-indexed sheet number within the ballot style

    side

    string - "front" or "back"

    Indicates side of the sheet

    column

    number

    Column position of the bubble in the timing mark grid

    type

    string - "write-in"

    Indicates this is a write-in option position

    sheetNumber

    number

    1-indexed sheet number within the ballot style

    side

    string - "front" or "back"

    Indicates side of the sheet

    column

    number

    Column position of the bubble in the timing mark grid

    x

    number

    Column start of the rectangle

    y

    number

    Row start of the rectangle

    width

    number

    Width of the rectangle

    height

    number

    Height of the rectangle

    Contest
    Contest
    https://www.base64-image.dearrow-up-right
    ballot hash
    Precinct
    ballot hash
    IETF language tagsarrow-up-right
    Hand Marked Ballots
    herearrow-up-right
    Relationship of grid layouts to other entities in the election definition
    letter, legal, custom-8.5x17, custom-8.5x18, custom-8.5x21, custom-8.5x22
    "description": "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO1n0X8AAAAASUVORK5CYII=\">"
    {
      "ballotStrings": {
        "en": {
           ...
          "candidateNames": {
             "john-doe": "John Doe",
             "jane-doe": "Jane Doe".
             ...
          },
          "electionTitle": "General Election",
          "hmpbOfficialBallot": "Official Ballot",
          ...
        }
        "es-US": {
          ...
          "candidateNames": {
             "john-doe": "John Doe",
             "jane-doe": "Jane Doe".
             ...
          },
          "electionTitle": "Elecciones generales",
          "hmpbOfficialBallot": "Boleta oficial",
          ...
        }
      },
      ...
    }
    Grid Layouts
    See Grid Layouts Section
    County
    District
    Party
    Precinct
    Yes-No Contest Option
    Contest
    Contest
    District
    Party
    Party
    Precinct
    Contest
    Candidate
    Yes-No Contest Option
    Contest
    Rectangle

    Logging

    All VxSuite applications use the same framework to log user actions, application processes, and errors. The logs are persisted to disk and can be exported by election managers or system administrators.

    hashtag
    Application Log Events

    VxSuite applications use a shared logging libraryarrow-up-right to capture required or otherwise important application log events. The core metadata for each application log event maps roughly to VVSG 2.0 standards, with some additional fields:

    • Log Event ID - The unique identifier for each event. The full list of log event IDs with descriptions is included in the automatically generated log .

    • Log Event Type - Describes whether the event involves an action or a status update, and whether it originated with a user, the application, or the larger system. Log event types can be thought of as categories whereas log event IDs are more specific. Every log event type includes many log event IDs under it. The full list of log event types with descriptions is included in the automatically generated log .

    • User - If there was an authenticated user role at the time of a user action, describes the role as system_administrator, election_manager, poll_worker or vendor. If no user was authenticated, then unknown. If event does not originate from the user but rather automatically from the application or operating system, it will be system.

    • Disposition - For actions that can fail or succeed, success or failure. Otherwise na for not applicable.

    • Source - Indicates where in the system's architecture the log came from, whether it be the frontend renderer, the frontend server, the backend server, a hardware daemon, or the operating system.

    • Message - The log message itself, which may not be present if the log event ID sufficiently describes the event.

    • Other Metadata - Other metadata can be freely included. For example, if a user adds manual tallies on VxAdmin, the metadata of those manual tallies will be included in the logging.

    • Time Written - Timestamp of when the log was created.

    hashtag
    Log Management

    The shared logging library formats the log events as JSON and pushes them to application processes' stdout. All stdout output from the application processes - both the application log events and any process output - is sent to the system's logger utility and assigned the tag votingworksapp.

    VxSuite uses rsyslog, an advanced implementation of the Syslog protocol, to centralize and manage logs from votingworksapp and other sources. rsyslog has advantages over the built-in Linux syslog implementation of the Syslog protocol, including JSON structured messages, advanced filtering, and increased performance. Using rsyslog, different types of logs are directed to different log files in /var/log/votingworks/:

    Log File
    Contents

    vx-logs.log is the most important and informative file in most cases. The other files rarely need to be referenced. All logs required by VVSG certification will exist in vx-logs.log.

    Because each log file can grow very large, the application will rotate logs if necessary with the logrotate utility on each startup. Previous log files will be compressed and suffixed with a timestamp.

    Including the various log files and log rotation, below is an example of the list of log files that might appear on a device:

    hashtag
    Default VotingWorks Log Format

    The default VotingWorks log format is how logs are formatted when emitted from the application and how they appear in vx-logs.log. It is a direct mapping of the fields.

    hashtag
    CDF Log Format

    Logs can be exported in CDF format, in which case the vx-logs.log file is replaced by a vx-logs.cdf.json file with the logging attributes mapped as follows:

    CDF Attribute

    hashtag
    Error Logs

    The log export flow exposed in all VxSuite applications also allows for exporting an errors-only version of the logs. This will only export a log file for logs where the disposition is "failure" and covers all software and hardware errors that have occurred on the machine.

    hashtag
    15.1-D Logging Event Types Table

    A full list of all logs made in the system with a description of each one can be found . For convenience a table is provided below mapping Table 15-1 from VVSG 2.0 Requirement 15.1-D to the appropriate logs in the VotingWorks system. The details and descriptions provided in Table 15-1 have been simplified for brevity in this table. Some items have been expanded into multiple rows to more precisely specify linked logs.

    hashtag
    General System Functions

    System Event
    Detail
    Logging Details

    hashtag
    Authentication and Access Control

    System Event
    Detail
    Logging Details

    hashtag
    Networking

    System Event
    Logging Details

    hashtag
    Software

    System Event
    Detail
    Logging Details

    hashtag
    Voting Functions

    System Event
    Detail
    Logging Details

    A VotingWorks defined identifier for the type of event, such as "save-election-package-complete"

    Event.Disposition

    "success", "failure", "na", or "other"

    Event.OtherDisposition

    If the disposition is "other", the details appear here

    Event.Sequence

    The index of the log in the list of logs, zero-indexed

    Event.TimeStamp

    ISO formatted timestamp of when the event was logged

    Event.Type

    Log event type

    Event.Description

    Log message

    Event.Details

    JSON including the log source and any additional logging metadata

    Event.UserId

    The user at the time of the log

    Critical system status messages

    Diagnostic and status messages upon startup

    machine-boot-init machine-boot-complete

    Critical system status messages

    The "zero totals" check

    polls-opened toggled-test-mode

    Critical system status messages

    The initiation or termination of scanner and communications equipment operation

    scanner-state-machine-event

    scanner-state-machine-transition

    mark-scan-state-machine-event

    paper-handler-state-machine-transition

    Critical system status messages

    Printer errors

    printer-status-changed and printer-print-complete with a failure Disposition cover VxScan. paper-handler-state-machine-transition covers VxMarkScan. For the VxAdmin printer, we emit a printer-config-added log when VxAdmin successfully registers the printer as connected, and we emit a printer-config-removed log when VxAdmin registers the printer as disconnected. If the printer is connected but the last printer log is printer-config-removed, it can be inferred that there's a problem.

    For the VxCentralScan imprinter, an imprinter-status

    Critical system status messages

    Detection or remediation of malware or other malicious software

    Malware or other malicious software is prevented from being added to VotingWorks systems via our design. Rather than using a traditional "allowlist" that is only applicable to malware, we create a system-wide hash of the expected system content. If anything changes, whether via malware or some other method, the system will no longer boot. Failed cryptographic boot validation intentionally stops the boot process before logging processes can even spin up, so no log will be found in the log file for this case. A representative message will be displayed on screen, however, e.g., "Verity device detected corruption after activation."

    If you encounter a failed cryptographic boot validation - since it may be indicative of malware - make note of the error message and reach out to VotingWorks.

    Critical system status messages

    Cryptographic boot validation success/failure

    dmverity-boot with a success Disposition indicates successful cryptographic boot validation. Failed cryptographic boot validation intentionally stops the boot process before logging processes can even spin up, so no log will be found in the log file for this case. A representative message will be displayed on screen, however, e.g., "Verity device detected corruption after activation." If you encounter a failed cryptographic boot validation - since it may be indicative of malware - make note of the error message and reach out to VotingWorks.

    Non-critical status messages

    device-attached usb-device-change-detected scanner-state-machine-event

    scanner-state-machine-transition

    mark-scan-state-machine-event

    paper-handler-state-machine-transition Various other logs. In the event of failure, please make note of the failure and reach out to VotingWorks.

    Events that require election official intervention

    device-unattached scanner-state-machine-event

    scanner-state-machine-transition

    mark-scan-state-machine-event

    paper-handler-state-machine-transition auth-login Various other logs

    Device shutdown and restarts

    machine-shutdown-init indicates the start of a shutdown, and machine-shutdown-complete indicates the successful completion of a shutdown. A restart will begin with the above two shutdown logs and then be followed by a machine-boot-init log, which indicates the start of a boot, and a machine-boot-complete log, which indicates the successful completion of a boot. Abnormal shutdowns and restarts can take many forms in the logs. A machine-shutdown-init log without a corresponding machine-shutdown-complete log indicates a failed shutdown or restart. A machine-boot-init log without a corresponding machine-boot-complete log indicates a failed boot or restart. Finally, a machine-boot-init log without a previous machine-shutdown-complete

    Changes to system configuration settings

    It is not possible to change these configuration settings, and any attempt to do so will result in a sudo-action log.

    Integrity checks for executables, configuration files, data, and logs

    For election package configuration, a failed integrity check will result in an election-configured log with a failure Disposition and Election package authentication erred in the message.

    For CVR import, a failed integrity check will result in an import-cast-vote-records-complete log with a failure Disposition and authentication-error in the error details.

    All of the above logs, if seen with a success Disposition, indicate successful integrity checks.

    The addition and deletion of files

    The overwhelming majority of machine data is stored in a database, the creation and destruction of which are captured in database-create-complete and database-reset-complete logs.

    The only other files stored on the file system are scan images on VxCentralScan and VxScan. On VxCentralScan, scan image file creations pair with scan-sheet-complete logs, and scan image file deletions (without a complete unconfiguration) pair with clear-ballot-data-complete and delete-cvr-batch-complete. On VxScan, scan image file creations pair with scanner-state-machine-transition logs, where the body includes Transitioned to: "interpreting", and scan image file deletions (without a complete unconfiguration) pair with toggled-test-mode logs.

    System readiness results

    System pass or fail of hardware and software test for system readiness

    diagnostic-init diagnostic-complete election-configured polls-opened toggled-test-mode

    System readiness results

    Identification of the software release, identification of the election to be processed, polling place identification, and the results of the software and hardware diagnostic tests

    The software release can be verified using , for which a signed-hash-validation-complete log will be emitted. The election, specifically ballot hash, can be found in the election-configured log. The polling place can be found in the polls-opened log as well as the precinct-configuration-changed log if a change was made from the default selection. The results of software and hardware diagnostic tests can be found in diagnostic-complete logs.

    System readiness results

    Pass or fail of ballot style compatibility and integrity test

    The election-configured log with a success Disposition indicates a pass. That log with a failure Disposition indicates a fail. More on integrity checks a few rows up in this table.

    System readiness results

    Pass or fail of system test data removal

    On all machines other than VxAdmin, the toggled-test-mode log with a success Disposition indicates a pass. There is no expected circumstance under which a toggled-test-mode log with a failure Disposition will be emitted. If such an error were to occur, the system would surface an error screen indicating an abnormal/unexpected error. VxCentralScan does disallow switching from official mode to test mode if ballots have been scanned and corresponding CVRs have not yet been exported, but this is accomplished by completely disabling the toggle. On VxAdmin, the clear-imported-cast-vote-records-complete log with a success Disposition indicates a pass. There is no expected circumstance under which a clear-imported-cast-vote-records log with a failure Disposition will be emitted. If such an error were to occur, the system would surface an error screen indicating an abnormal/unexpected error.

    System readiness results

    Zero totals of data paths and memory locations for vote recording

    On VxScan, the polls-opened log with a success Disposition indicates a pass. A polls-opened log with a failure Disposition and User prevented from opening polls because ballots have already been scanned in the body would hypothetically indicate a fail, but this log cannot actually be emitted in practice as we prevent any ballot scanning until polls have been opened. On VxAdmin and VxCentralScan, a data-check-on-startup log indicates in its message whether election results or scanned ballot data are present in the database at machine startup.

    Removable media events

    usb-device-change-detected

    Backup and restore

    On VxCentralScan and VxScan, full CVR exports serve as backups. These pair with cast-vote-records-complete logs. This data is not, however, intended to be loaded back onto VxCentralScan and VxScan, so there is not an equivalent restore operation. Because VxMarkScan does not tabulate, there are no CVRs on it to backup.

    On all machines, user-triggered exports of reports and logs to USB drives pair with file-saved logs. This data is also not meant to be loaded back into the system.

    Access control related events

    Attempts to exceed privileges

    sudo-action with a message indicating that the action was disallowed

    Access control related events

    All access attempts to application and underlying system resources

    To access underlying system resources, one would need to either break out of kiosk mode (which is not possible) or have access to a vendor card and its PIN. One would then need to use sudo. As such, a sudo-action log would be emitted.

    Access control related events

    Changes to the access control configuration of the voting device

    The access control configuration is controlled by the system settings file within the election package. As such, the access control configuration can only be changed by reconfiguring with a new election package. This emits an election-configured log.

    User account and role (or groups) management activity

    Addition and deletion of user accounts and roles

    New users are created by programming smart cards, for which a smart-card-program-complete log is emitted.

    Users can be "deleted" by unprogramming smart cards, for which a smart-card-unprogram-complete log is emitted.

    User account and role (or groups) management activity

    User account and role suspension and reactivation

    As noted above, smart-card-program-complete and smart-card-unprogram-complete cover this.

    User account and role (or groups) management activity

    Changes to account or role security attributes such as password length, access levels, login restrictions, and permissions

    Security settings are controlled by the system settings file within the election package. As such, security settings can only be changed by reconfiguring with a new election package. This emits an election-configured log.

    User account and role (or groups) management activity

    Administrator account and role password resets

    The system administrator role is itself smart card authenticated, and password changes are accomplished by reprogramming, so smart-card-program-complete covers this. For the vendor menu, accessed via a vendor smart card with a PIN and then additionally gated by a vendor password, changing the latter password results in a password-change log. All other substantive vendor actions result in a sudo-action log.

    Abnormal process exits

    unknown-error There is no expected circumstance under which a process will exit abnormally. If such an error were to occur, the system would surface an error screen indicating an abnormal/unexpected error.

    Successful and failed database connection attempts (if a database is used)

    database-connect-init database-connect-complete There is no expected circumstance under which a database connection attempt will fail. If such an error were to occur, the system would surface an error screen indicating an abnormal/unexpected error.

    Changes to cryptographic keys

    A machine TPM key is created during initial configuration by VotingWorks after software imaging. This operation pairs with a sudo-action log that references a generate-key.sh command. No additional keys can be added, nor can this key be deleted. The key can however be changed by VotingWorks, via use of a vendor smart card. The change will also show up in the logs as a sudo-action that references the generate-key.sh command.

    Voting events

    Success or failure of log and election results exportation

    export-cast-vote-record-complete file-saved

    vx-logs.log

    Key logs required by VVSG 2.0 or otherwise critical for understanding the behavior of the application or device, including:

    • all application log events

    • USB device connection events

    • machine boot and shutdown events

    • all sudo actions

    • password events

    • dm-verity events

    auth.log

    All operating system authentication-related events. Note that this will not include voting system authentication events such as logging in with a smart card - these events are in vx-logs.log

    syslog

    All other events emitted from the application or the operating system that do not fall into the other log files.

    ElectionEventLog.GeneratedTime

    ISO formatted timestamp of when logs were exported

    ElectionEventLog.Device

    List containing only the current device

    Device.Type

    The CDF DeviceType matching the type of machine:

    • VxAdmin -> "ems"

    • VxScan -> "scan-single"

    • VxCentralScan -> "scan-batch"

    • VxMarkScan -> "bmd"

    Device.Id

    The serial number of the device

    Device.Version

    The software version e.g. "v3.1.2"

    Device.Event

    List of all events

    Device generated error and exception messages

    Entries into exception handling routines

    Errors can be logged with any LogEventId but are indicated by a failure Disposition. All logs contain a Source. Every error is logged when it occurs, and each log can be assumed to correspond to one instance of that error occurring unless otherwise stated in the log. Of particular note are logs with LogEventId unknown-error. These represent unexpected system errors, as opposed to user errors.

    Device generated error and exception messages

    Notifications of physical violations of security

    VxMarkScan physical violations of security are covered by printer-scanner cover-open logs. These will have a LogEventId of paper-handler-state-machine-transition with a body Transitioned to: "cover_opened_unauthorized"

    The VxScan scanner cover is intended to be opened by poll workers for maintenance, so this does not constitute a physical violation of security. Nonetheless, logs are also emitted for this case. These will have a LogEventId of scanner-state-machine-transition with body Transitioned to: "coverOpen"

    Device generated error and exception messages

    Other exception events such as power failures, failure of critical hardware components, data transmission errors, or other types of operating anomalies

    On VxMarkScan, hardware failures are covered by logs with LogEventId paper-handler-state-machine-transition and body Transitioned to: "no_hardware"

    On VxScan, hardware failures are covered by logs with LogEventId scanner-state-machine-transition and body Transitioned to: "disconnected"

    Device generated error and exception messages

    Recovery actions taken

    Authentication related events

    Login/logoff events

    auth-login auth-logout auth-pin-entry

    Account lockout events

    auth-pin-entry-lockout auth-logout where the log's reason field contains session_expired on VxMarkScan and VxScan, and machine_locked_by_session_expiry on VxAdmin and VxCentralScan

    Password changes

    smart-card-program-complete covers all smart card PIN changes. For the vendor menu, accessed via a vendor smart card with a PIN and then additionally gated by a vendor password, changing the latter password results in a password-change log.

    Access control related events

    Use of privileges (such as a user running a process as an administrator)

    Enabling or disabling networking functionality

    It is not possible to enable wired or wireless networking. Any attempt to bypass protections in place blocking this will result in an error and a sudo-action log.

    Installing, upgrading, patching, or modifying software or firmware

    Because we update software by completely reimaging machines, all logs prior to updating are cleared. We procedurally make sure that logs are exported before beginning a software update. A sudo-action log that references an expand-var-filesystem.sh command is indicative of a freshly imaged/updated machine. The software version/hash, both before and after update, can be verified using Signed Hash Validation, for which a signed-hash-validation-complete log will be emitted. The software version/hash is also logged on every boot in a subset of the dmverity-boot logs. Searching for verity.hash in the vx-logs.log file will help you hone in on these logs.

    Changes to configuration settings

    Changes to critical function settings, including location of election definition file, contents of the election definition file, vote reporting, location of logs, and voting device configuration settings

    The location of the election definition and logs cannot be changed; both are stored in static locations. Changes to the contents of the election definition pair with election-configured and election-unconfigured logs. The are no controls outside of election definition configuration that affect how votes are reported. Other voting device configuration settings are covered by continuous-export-toggled, double-sheet-toggled, sound-toggled, and toggled-test-mode logs.

    Changes to configuration settings

    Changes to device settings including, but not limited to, enabling and disabling services

    As noted above, device settings are covered by continuous-export-toggled, double-sheet-toggled, sound-toggled, and toggled-test-mode logs.

    Changes to configuration settings

    Starting and stopping processes

    Ballot definition and modification

    election-configured

    election-unconfigured

    Voting events

    Opening and closing polls

    polls-opened

    polls-closed

    voting-paused

    voting-resumed

    reset-polls-to-paused These logging events are the internal tests that verify that the prescribed closing or suspension procedures have been followed.

    Voting events

    Casting a vote

    VxMarkScan: vote-cast VxScan: scanner-state-machine-event with the event scanStart to indicate the voter has started feeding a ballot. If the voter has to cast from adjudication there will be an accept event.

    Voting events

    Canceling a vote during verification

    documentationarrow-up-right
    documentationarrow-up-right
    herearrow-up-right
    Application Log Events

    Event.Id

    Recovery actions will vary for every error and can therefore map to any log. Recommended recovery actions for user-facing errors are documented in our user manual under the following pages:

    sudo-action

    For lower-level hardware daemons run in a separate process, we have process-started and process-terminated logs. The only machine that currently runs a lower-level hardware daemon in a separate process is VxMarkScan for the accessible controller and PAT input. The only known circumstance under which a process-terminated log can be emitted is during VxMarkScan electrical testing. Shocking the PAT input with an ESD pulse can cause the hardware daemon to terminate and restart.

    VxMarkScan: ballot-invalidated VxScan: scanner-state-machine-event with event reject

    /var/log/votingworks/vx-logs.log
    /var/log/votingworks/vx-logs.log-20241104.gz
    /var/log/votingworks/vx-logs.log-20241105.gz
    /var/log/votingworks/auth.log
    /var/log/votingworks/syslog
    /var/log/votingworks/syslog-20241105.gz
    {
        "timeLogWritten":"2024-11-05T15:51:51.246232-08:00",
        "host":"VotingWorks",
        "source":"vx-scan-backend",
        "eventId":"auth-login",
        "eventType":"user-action",
        "user":"poll_worker",
        "message":"User logged in.",
        "disposition":"success",
    }
    log is emitted whenever paper scanning is initiated. The log indicates in its message whether or not the imprinter is registering as attached. It can be inferred that there's a problem if the imprinter is attached, but the log indicates that it is not attached. Note that the VxCentralScan Fujitsu scanner requires you to power cycle it after you either attach or detach the imprinter. If you detach the imprinter while the Fujitsu scanner is on, an indicator on the Fujitsu scanner screen will say that the imprinter cover is open. No scans are accepted in this state. You have to power cycle the Fujitsu scanner to dismiss the warning and renable scanning. After this is done, the logs will indicate on next scan that the imprinter is detached. Vice versa, if you attach the imprinter while the Fujitsu scanner is on, the device jams. It takes a power cycle to get it to register the imprinter attachment.
    log indicates that the last shutdown was abnormal and likely the result of a loss of power rather than user-initiated.
    On all machines, user-triggered exports of reports and logs to USB drives pair with file-saved logs. We don't expose functionality to delete these files individually. They can be cleared by formatting the USB drive, however, for which a usb-drive-format-complete log will be emitted.
    System Integrity
    Signed Hash Validation
    Configure VxAdmin
    Save Election Package
    VxScan Diagnostics
    VxCentralScan Diagnostics
    VxAdmin Diagnostics
    VxCentralScan Diagnostics
    VxScan Diagnostics
    VxMarkScan Diagnostics
    Setup Inspection
    VxMarkScan Hardware Setup
    VxMarkScan
    Open and Close Polls
    Voting Sessions
    Setting Date & Time
    Smart Cards and User Roles
    USB Formatting
    Tally Results
    Adjudication
    Manual Tallies
    Reports
    VxAdmin Error Messages
    VxCentralScan Error Messages
    VxMarkScan Error Messages
    VxScan Error Messages
    Configure VxCentralScan
    Printer Management
    Scanner Management
    Configure VxScan
    Opening Polls
    Closing Polls
    Additional Poll Worker Actions
    Assisting Voters
    Saving CVRs
    Scan Ballot Batches
    Adjudicate Ballots
    Saving Cast Vote Records (CVRs)