Only this pageAll pages
Powered by GitBook
1 of 72

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...

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

Ballot Size

There are six valid ballot sizes. All are 8.5 inches in width, but vary in height:

Name
Length
Width

Letter

11"

8.5"

Legal

14"

8.5"

Custom 17"

17"

8.5"

Custom 22"

22"

8.5"

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

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

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.

QR Code Metadata

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

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

  • Test Ballot Flag - indicates whether the ballot is a test ballot or an official ballot

  • Ballot Type (Precinct, Absentee, or Provisional)

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.

Bubble Format

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

Dimension
Measurement

Width

0.20"

Height

0.13"

Border Radius

0.7"

Line Thickness

1px (0.265mm)

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

Complete Example

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

Machine Marked Ballots

After a voter is done making vote selections with VxMark, the machine will print a ballot representing the selections. The voter reviews the ballot, after which it is deposited into the attached ballot box. Eventually, those ballots are scanned at VxScan or VxCentralScan.

Ballot Layout

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.

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

Multi-Lingual Ballots

QR Code

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.

Core Election Attributes and Relationships

Election

The Election entity is the top-level entity that contains all other entities.

Ballot Layout

The ballot layout entity includes basic information about the physical ballots used for the election.

The paperSize attribute accepts the following valid options:

The metadataEncoding attribute must be "qr-code".

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.

Contest

There are two types of contests - candidate contests and yes-no contests. Both types share core attributes:

Candidate Contest

Candidate

Yes-No Contest

Yes-No Contest Option

County

One and only one county is associated with each election.

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.

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

Precinct

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.

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"

Election-Specific Text

  1. The language-specific strings are used to accommodate multi-lingual voting on VxMark

The election-specific ballotStrings recognized by the system are the following:

Example

Grid Layouts

gridLayouts is an array which contains entities with the following attributes:

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.

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.

Option Grid Position

Write-In Grid Position

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.

Rectangle

Examples

VxScan Polls Reports

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:

  • 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.

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

The ballot counts table provides the count of hand marked vs. machine marked ballots. For elections with multi-sheet ballots, it provides counts per sheet.

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.

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.

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.

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 write-in adjudication or auditing

  • 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 write-in adjudication.

In addition, there is a metadata file that applies to the entire export at the root of the directory, metadata.json.

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.

Including Ballot Images

In VxScan, ballot images and layouts are always included. In VxCentralScan, ballot images and layouts are only included in the cast vote record export if the ballot has write-ins that may require adjudication. When exporting a backup from VxCentralScan, however, ballot images and layouts are included for all ballots.

Layouts are not included for machine marked ballots.

Including Rejected Ballots

In VxScan, images of rejected ballots are always included. In VxCentralScan, images of rejected ballots are not included in the cast vote record export but are included in the backup. There are no layout files or cast vote record report for rejected ballots because they are often uninterpretable. When rejected ballots are included, they will appear in the directory with the prefix rejected-, as in the following example:

Cast Vote Record Report

CDF Implementation

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.

VxSuite Required Fields

Report Metadata

CastVoteRecordReport

CastVoteRecordReport.ReportingDevices

Only one ReportingDevice is ever listed:

CastVoteRecordReport.Party

CastVoteRecordReport.GpUnit

CastVoteRecordReport.Election

Cast Vote Record Attributes

Each cast vote record includes a set of ballot metadata attributes:

Ballot Images

The CVR.BallotImage attribute exists when there are images accompanying the cast vote record. If it exists, it always contains images for both sides of the ballot. Its attributes are as follows:

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.

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 and is included purely for auditability. 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

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:

Representing Votes

The CVRContest class within each snapshot contains a list of vote records by contest. The fields are used as follows:

Ballot Images

Ballot images are .jpg files. They are included in the cast vote record in order to be used for write-in adjudication or auditing. Ballot images are generated by the scanning hardware and then normalized to reduce skew and enforce a consistent orientation. Images from VxCentralScan are in grayscale while images for VxScan are in black and white.

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 write-in adjudication.

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:

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.

Ballot must adhere to

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

In addition, the QR code includes the . 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, view the .

Ballot Component
Details

If VxMark 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 VxMark ballot may have translations specified in the , which will then be used when printing the ballot.

The QR codes on VxMark 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, view the .

Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description

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
Attribute
Type
Description

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
Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description

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.

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:

Including the translations in the election definition means they are included in the and cannot be changed without invalidating older ballots.

Description
Key
Value

The language codes used are the for supported VxSuite languages: English, Spanish, Simplified Chinese, and Traditional Chinese.

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 .

Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description
Attribute
Type
Description

Election definition examples are located in the vxsuite repository, such as .

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

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.

CDF Class
Additionally Required Attributes

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.

CDF Attribute
Usage
CDF Attribute
Usage

The list of parties in the cast vote record report is mapped directly from the list in the election definition:

CDF Attribute
Usage

GpUnits are created for each in the election, for the , and for the state:

CDF Attribute
Usage

The Election class has values mapped to it directly from the :

CDF Attribute
Usage
CDF Attribute
Usage
CDF Attribute
Usage
CDF Attribute
Usage
CDF Attribute
Usage
Attribute
Usage
Attribute
Usage
Ballot Layout
ballot encoder documentation

paperSize

string

Indicates physical length of the ballot

metadataEncoding

string

Indicates how the ballot metadata will be encoded on the ballot

letter, legal, custom-8.5x17, custom-8.5x18, custom-8.5x21, custom-8.5x22

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"

{
  "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",
      ...
    }
  },
  ...
}

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

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

candidate votes + undervotes + overvotes = ballots * votes allowed
- 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
    - ...

CVR

BallotStyleId, BallotStyleUnitId, BatchId, CreatingDeviceId, UniqueId

CVRContest

CVRContestSelection

CVRContestSelection

  • ContestSelectionId

  • SelectionPosition is limited to length 1

CVRSnapshot

CVRContest

@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

Location

Location of the image file relative to the report, such as:

file:864a2854-ee26-4223-8097-9633b7bed096-front.jpg

Hash.Type

Fixed to "sha-256"

Hash.Value

  • No Images: Undefined

  • Images & Layouts: {SHA256 hash of image}-{SHA256 hash of layout}

  • Images Only: SHA256 hash of image

864a2854-ee26-4223-8097-9633b7bed096-modified

CVRSnapshot.Status

Fixed to ["other"]

CVRSnapshot.OtherStatus

JSON blob representing the ballot type. The possible values are "absentee", "precinct", or "provisional".

{
  ballotType: "absentee"
}

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

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

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

scannerId

The serial number of the scanner

IETF language tags
Hand Marked Ballots
here
NIST JSON schema
VxSuite JSON schema
election package
election definition
election definition's ballot strings
Contest
Contest
Precinct
Party
Precinct
County
ballot encoder documentation
QR codes on hand marked ballots

Election Seal

The seal included in the election definition

Ballot Title

The title is either "Unofficial Test Ballot" or "Official Ballot" depending whether VxMark 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 VxMark.

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

ballotLayout

Physical ballot metadata

ballotStrings

ballotStyles

All ballot styles

contests

All contests

gridLayouts

county

County metadata

date

string - YYYY-MM-DD

Date of the election

districts

All districts

id

string

Unique identifier

parties

All parties

precincts

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

id

string

Unique identifier

precincts

The IDs of all precincts which use the ballot style

districts

The IDs of all districts whose contests are included in the ballot style

partyId

Optional. The ID of the party to which the ballot belongs, if a primary

languages

array - string

Optional. The language codes for the languages covered by the ballot style

id

string

Unique identifier

districtId

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

Candidate options for the contest

allowWriteIns

boolean

Whether the contest allows write-ins

partyId

Optional. The ID of the party to which the contest belongs, if a primary

termDescription

string

Optional. Description of the term of the position, such as "For three years"

id

string

Unique identifier

name

string

Name as it appears on the ballot

partyIds

Optional. The IDs of the parties associated with the candidate. The party name will appear next to the candidate

id

string

Contest description

yesOption

"Yes" option

noOption

"No" option

Ballot Language

ballotLanguage

string

Ballot Style IDs

ballotStyleId

Candidate Names

candidateName

Contest Descriptions

contestDescription

Contest Option Labels

contestOptionLabel

Contest Terms

contestTerm

Contest Titles

contestTitle

County Name

countyName

string

District Names

districtName

Election Date

electionDate

string

Election Title

electionTitle

string

Party Full Names

partyFullName

Party Names

partyName

Precinct Names

precinctName

State Name

stateName

string

ballotStyleId

Identifies the ballot style

optionBoundsFromTargetMark

Describes where the entire contest option area sits relative to the bubble

gridPositions

Describes bubble and write-in positions on the ballot

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

row

number

Row position of the bubble in the timing mark grid

contestId

Contest identifier

optionId

Option identifier

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

row

number

Row position of the bubble in the timing mark grid

contestId

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

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

ReportGeneratingDeviceIds

The scanner serial number

@id

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

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

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

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

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

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

VxAdmin Results Exports

VxAdmin supports a variety of results exports.

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.

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

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

Tally Reports

Basic Structure

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:

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:

Note that filters and groups can be combined.

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".

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.

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

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

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

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 appear in the adjudicated write-in bucket if it is not relevant to the results

  • When invalid, the write-in becomes an undervote

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.

Ballot Count Reports

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

The ballot counts are broken down by ballot type - "HMPB" (for hand marked ballots), "BMD" (for machine marked ballots), and "manual" (for manually entered results, if applicable).

If there are multi-sheet ballots, the hand marked ballot counts may have sheet counts specified. The ballot count is determined by counting the first sheet of each ballot style.

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:

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

Header
Values

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

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

VxCentralScan Function

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

Configuration

Ballot Mode

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.

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.

Batch Scanning

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.

Batch Management

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.

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.

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.

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

  • 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.

Exporting CVRs

CVRs must be exported onto a USB drive and taken to VxAdmin for aggregation and reporting. The election managers has options to either save CVRs or save a backup. When saving CVRs, ballot images are only included for ballots with write-ins and rejected ballots are not included. A backup is simply a CVR export with images for all ballots and images for rejected ballots.

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.

VxScan Function

VxScan is the system's precinct scanner into which voters cast their ballots directly.

Hardware Management

Printer Management

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:

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.

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 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.

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.

Configuration

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.

Ballot Mode

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.

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.

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.

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.

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.

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

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).

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.

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 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.

VxAdmin & VxCentralScan Hardware

Overview

Laptop

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

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.

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.

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.

Bill of Materials

Shared Components (Laptop & Accessories)

VxAdmin Components (Printer)

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.

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:

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.

User Roles

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 VxMark. On both devices, the poll worker card is used to open and close polls on election day. On VxMark, 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.

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

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.

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.

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.

Voter Mode

While the authentication model only includes the four aforementioned roles, one can conceptually describe a "voter mode" on the precinct devices. On VxMark, 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.

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).

Configuration and Election Packages

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 VxMark, VxScan, and VxCentralScan must be signed and unsigned election packages will be rejected.

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.

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.

CVR Management

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 interpreted votes 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.

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 VxMark, 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.

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.

Write-In Adjudication

When ballots with write-ins are scanned at VxScan or VxCentralScan, they have not yet been adjudicated. The polls closed report at VxScan treats all write-ins simply as a generic "Write-In" and all unmarked write-ins as undervotes.

VxAdmin allows election managers to perform on-screen write-in adjudication. Each contest is adjudicated individually. The election manager can work through the queue of write-ins for that contest. The queue is ordered by least to most recently loaded into VxAdmin. Because multiple write-ins for a single CVR are loaded together, write-ins that appear on the same ballot sheet will appear next to each other in the queue.

The user can adjudicate the write-in in one of three ways:

  • Official Candidate: the list of official candidates for the given contest will be displayed and the write-in can be assigned to any official candidate

  • Unofficial Candidates: the list of unofficial candidates defined for the given contest by the election manager will be displayed and the write-in can be assigned to any unofficial candidate

  • Undervote: the write-in can be deemed invalid and will be considered in tallies as an undervote

Adjudications are immediately persisted to the data store. Adjudications can be changed or deselected.

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.

Invalidating or Validating Marks

In most cases, the adjudication reclassifies a vote for an unadjudicated write-in to a write-in candidate. But in some cases, the adjudication effectively reclassifies a mark as a non-mark or vice versa.

If a marked write-in is adjudicated as an undervote, in addition to updating the associated write-ins record, VxAdmin will create a vote_adjudications record representing the switch from an indication to a non-indication. If an unmarked write-in is adjudicated for a candidate, VxAdmin will create a vote_adjudications record representing the switch from a non-indication to an indication.

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.

Tallying & Reports

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.

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.

The write-in adjudication report is simply the results of the write-in adjudication aggregation step, without filter or group, formatted into a PDF.

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.

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.

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

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.

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.

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 modes:

  • The system administrator may unconfigure VxAdmin entirely, removing the election configuration in addition to all tallies and adjudications.

  • The election manager may remove all tallies and adjudications at once, leaving the election configuration in place.

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.

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, VxMark, 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.

Operating System

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.

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.

kiosk-browser

Application Frontend Server

Application Backend Server

Application Data Management

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:

Firmware for embedded devices such as screens and speakers is bundled with the operating system.

Software Independence

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 VxMark. 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. VxMark'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.

Key VotingWorks Repositories

There are four code repositories relevant to the voting system:

Key Dependency Chart

Traceability of Procured Software

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:

Failure Recovery

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

  • 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

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.

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.

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.

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.

Other Shared Software Patterns

VxScan Hardware

Overview

VxScan consists of two main components - the collapsible ballot box and the scanner itself - which are secured together during setup.

Ballot Box

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.

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.

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.

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.

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 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 green release lever 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.

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.

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.

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.

COTS Components

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.

VxMark Function

VxMark 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. VxMark is not a tabulator, and the cast ballots must be later tabulated at VxScan or VxCentralScan.

Configuration

Precinct Selection

VxMark is not fully configured until the election manager selects a precinct for the device. When polls are open, VxMark will only allow marking ballots in the ballot styles for the configured precinct. The election manager may configure VxMark 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 VxMark by an election manager, even while polls are opened.

Ballot Mode

After initial configuration, VxMark 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 VxMark will be official ballots. In test ballot mode, the ballots printed at VxMark 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.

Unconfiguring

VxMark can be unconfigured by an election manager or system administrator.

Polls Management

After configuration, polls are initially closed. When polls closed, voting is not allowed on VxMark.

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 VxMark is unconfigured or switched from one ballot mode to another, with one exception discussed below.

VxMark 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.

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.

Display Formats & Interaction Modes

VxMark supports voting sessions in various display formats and interaction modes.

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.

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 VxMark's only touch screen gesture. It cannot be used horizontally to navigate between contests or pages and (VVSG 2.0 7.2-E).

Audio Tactile Mode - Accessible Controller

VxMark 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.

Limited Dexterity Mode - PAT Input

VxMark 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, VxMark 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.

Audio Format

As an alternative to the visual formats, the voter can listen to their ballot in an audio format. VxMark 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.

Language Support

VxMark 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.

Printer Access Control

VxMark'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, VxMark 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.

See

array -

array -

array -

array -

array -

array -

array -

array - IDs for

array - IDs for

string - ID for

string - ID for

array -

string - ID for

array - ID for

key-value pairs, IDs mapped to names

key-value pairs, IDs mapped to names

key-value pairs, IDs mapped to descriptions

key-value pairs, IDs mapped to labels

key-value pairs, IDs mapped to term descriptions

key-value pairs, IDs mapped to titles

key-value pairs, IDs mapped to names

key-value pairs, IDs mapped to their full names

key-value pairs, IDs mapped to their short names

key-value pairs, IDs mapped to names

string, ID for

string - ID of

string - ID of or

string - ID of

The generated date in

The election's

The election's

The without any specific cast vote record data. In other words, only data about the election and its contests

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 . In addition, full election results can be exported as an JSON file.

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

The 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.

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".

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

The write-in will be individually listed if it is

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.

User Manual Reference:

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 , official ballots will be allowed in test mode but exported CVRs will still be test CVRs.

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 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.

User Manual Reference:

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

User Manual Reference:

User Manual Reference:

Status
Meaning
Effect

During a polls transition, a polls report is 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.

User Manual Reference:

User Manual Reference:

VxScan 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.

User Manual Reference:

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 , official ballots will be allowed in test mode but exported CVRs will still be test CVRs.

User Manual Reference: , ,

While scanning is enabled, the scanner will grab and scan paper as soon as it is detected. The scanned image will be 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 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 . 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.

User Manual Reference:

The election package's file specifies the translations that will be used to replace all on screen voter messages when the language is switched.

User Manual Reference:

For details about the format of the polls reports, see .

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

All components for VxAdmin and VxCentralScan are commercial-off-the-shelf (COTS) components. Data sheets and related documentation are available .

Manufacturer
Component
Mfr. Part Number
Criticality
Manufacturer
Component
Mfr. Part Number
Criticality
Manufacturer
Component
Mfr. Part Number
Criticality
Component
Configuration

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: .

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 file within the election package.

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.

It's also possible to configure VxAdmin directly from a .json file rather than a full election package. The system will use default system settings and include no additional translations for application strings. Uploading a .json file directly is not recommended for general use because it means you are unable to customize system settings like ballot adjudication reasons. The option exists for development purposes. VxMark, VxScan, and VxCentralScan cannot be configured from an election definition alone and require a signed election package.

User Manual References: &

For extensive details on the authentication scheme, see the .

User Manual Reference:

User Manual Reference:

The core post-election (and pre-election testing) function of VxAdmin is loading, managing, and tallying (CVRs).

User Manual Reference:

The side of the ballot that the write-in appears on is rendered to the user, with options to zoom out and back in again. In the zoomed in view, the write-in area in question is highlighted. The location of the highlight is taken from the , which is included in the cast vote record and loaded into VxAdmin alongside the ballot image.

User Manual Reference:

User Manual Reference:

The final step is for the VxAdmin backend to format the vote tallies into one of and export the result onto a USB drive or, if it is a PDF document, print it.

User Manual Reference:

The system uses 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.

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.

The frontend is a application served from a server. All code for the application frontends are in the under apps/[app-name]/frontend.

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.

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.

Machine
Peripheral
Middleware Source

The voting system achieves software independence through the use of independent voter-verifiable paper records. All ballots are voter-verified paper ballots, either or .

— 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

— Our framework for building VxSuite and managing its dependencies, across versions and environments

Dependency
Version

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 .

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 .

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.

Much of 2.5 is additionally covered under .

User Manual Reference:

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 .

Manufacturer
Component
Mfr. Part Number
Criticality

VxMark is configured with a signed 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 file contains the translations for other text shown on screen. The election package's are played for the voter in audio-mode.

User Manual Reference:

User Manual Reference:

User Manual Reference:

User Manual Reference:

Date Time String Format
write-in adjudication report
NCName ID format
polls opened and closed reports
Ballot Layout
Ballot Strings
See Ballot Strings Section
Ballot Style
Contest
Grid Layouts
See Grid Layouts Section
County
District
Party
Precinct
Precinct
District
Party
District
Candidate
Party
Party
Yes-No Contest Option
Yes-No Contest Option
Ballot Style
Candidate
Contest
Yes-No Contest Option
Contest
Contest
District
Party
Party
Precinct
Ballot Style
Outset
Grid Position
Contest
Candidate
Yes-No Contest Option
Contest
Rectangle
cast vote record report
relevant to the results
QR Code

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.

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

Medium

Monoprice

USB-A to USB-B 2.0 6ft Cable

5438

Medium

HP

LaserJet Pro 4001dn Printer

2Z600F#BGJ

Medium

Lindy

RJ45 Port Blocker

40471

Low

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

High

Ricoh

fi-760PRB Imprinter (for fi-7600)

PA03740-D101

Medium

APC

Uninterruptible Power Supply

BN1500M2

Medium

Lindy

RJ45 Port Blocker

40471

Low

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

Near Field Communication

None

WWAN (Cellular)

None

WLAN (Wi-Fi)

None

Fingerprint Sensor

None

Smart Card Reader

Included

Country of Origin

TAA Designated

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

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

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

APC

Uninterruptible Power Supply

BN1500M2

Medium

VxScan Polls Reports
Access Control
Hash/Checksum Verification of Dependencies
Hashing of Continuously Exported Cast Vote Records
System Integrity
Ballot Interpretation
Diagnostics

System Limits

Election Definition Limits

Limit Type
Per
Value

Precincts

Election

1000

Candidates

Election

1000

Contests

Election

1000

Ballot Styles

Election

1000

Candidates

Contest

100

Vote For

Contest

50

Characters

Field Name

100

Component Limits

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.

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

VxMark

  • VxMark only supports 8" x 13.25" ballots as specified in Paper Ballot Specifications.

  • VxMark is limited to printing of 50 contest selections before needing to reduce text size to fit a summary ballot on a single sheet. VxMark can print a maximum of 100 contest selections with text-size reduction.

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

  • VxMark 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.

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.

Hand Marked Paper Ballots

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

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 an 11" ballot, which has a 32 x 39 timing mark grid, the maximum number of ballot positions is 1248 per page or 2496 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.

Supported Voting Variations & Languages

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.

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.

System Performance & Specifications

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

Supported Voting Variations & Languages

System Limits

Paper Ballot Specifications

Reliably Detectable Marks

Processing Capabilities

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.

Access Control

Artifact Authentication

System Integrity

Networking

Password and Credential Policies

Defense-in-Depth and Least Privilege

Cryptography

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.

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.

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", 22"

  • Weight: 105-177gsm

  • Coating: uncoated

  • Opacity: >90%

  • Color: white or any pastel color >70 brightness (to ensure it binarizes to white when scanned).

  • 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)

Ballot Marking Device Ballots

VxMark 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"

  • Length: 13.25"

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

TF 1467 paper is only provided in one configuration on white paper with a weight of 140gsm and thermally coated on one side. VxMark 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.

interpret the ballot
interpreted
hand marked ballot
in the documentation repository
access control documentation
cast vote records
VxAdmin's Results Export Formats
Debian
kiosk-browser repository
Electron
Chromium
React
Node.js
vxsuite repository
Node.js
vxsuite repository
Rust
SQLite
hand marked ballots
machine marked ballots
vxsuite
kiosk-browser
vxsuite-complete-system
vxsuite-build-system
TypeScript best practices and tooling
Rust best practices and tooling
examples of that process here
the documentation repository
generated
custom configured HP Elitebook 840 14" G11
election package
system administrator
interpreted ballot layout
system limits

All

Card reader

VxScan

Scanner

VotingWorks

VxScan

Printer

VotingWorks

VxMark

Printer-scanner

VotingWorks

VxMark

Accessible controller

VotingWorks

VxMark

PAT (sip and puff)

VotingWorks

VxAdmin

Printer

VxCentralScan

Scanner

Debian

12.2.0

Additional Debian Packages

Node.js

20.16.0

pnpm

8.15.5

Application Node Packages

Rust

1.81

Rust Packages

yarn

1.22.22

Electron

17.4.1

Chromium

98.0.4758.141

Kiosk Browser Node Packages

Ballot Interpretation

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.

The interpreter then identifies the timing mark grid. It begins by finding all shapes in the image. It then narrows the list of shapes down to ones that look like timing marks and then further narrows the list down to timing mark shapes that fall along the edges of the image in a line.

In the example above, the interpreter found all the timing marks correctly. Sometimes, it may not. In that case, it infers any missing timing marks. Once it has all the timing mark borders, it identifies the corners in order to construct a complete timing mark grid. If at any point the interpreter does not have enough information to confidently find the complete mark grid or if the detected grid is too rotated or skewed, it causes the application to reject the ballot.

Next the interpreter will 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 images right-side up if necessary:

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%.

The bubble mark scores are later compared against the definite mark threshold in the system settings and used to determine whether the voter made an indication that should be counted. The recommended default 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.

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%.

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.

VxMark Hardware

Overview

VxMark 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.

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:

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 VxMark.

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

Storage

VxMark 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.

Assembly

COTS Components

Manufacturer
Component
Mfr. Part Number
Criticality

Smartmatic

Ballot Marking Device

VSAP-150

High

APC

Uninterruptible Power Supply

BN1500M2

Medium

HID

Smart Card Reader

R31210375-1

Medium

LORELEI

Headphones

X6

Low

Williams Audio Visual

T-Coil Neckloop

NKL-001

Low

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.

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.

Common Diagnostics

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.

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.

Configuration

Election Identifier

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

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.

Precinct

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

Mark Thresholds

VxAdmin Diagnostics

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.

VxCentralScan Diagnostics

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.

VxScan Diagnostics

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.

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.

Speaker

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

VxMark Diagnostics

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.

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.

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.

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.

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. Marks are either valid or invalid — the voting system does not process any marks as ambiguous.

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.

Invalid Marks

Valid Marks

System Security, Auditing & Logging

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.

  • 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.

Code Links

Refer to the following code links for more details:

Hashing of Continuously Exported Cast Vote Records

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.

Merkle Tree Structure

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

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.

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

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:

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.

Code Links

Refer to the following code links for more details:

System Integrity

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 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.

  3. 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.

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.

  • 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.

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.

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.

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.

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.

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.

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.

Access Control

Certification of VxSuite Components

VxSuite is composed of individual machines, namely VxAdmin, VxCentralScan, VxMark, 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.

Certification relationships work as follows:

  • VotingWorks directly certifies the type of every component, i.e., VxAdmin machine, VxCentralScan machine, VxMark 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, VxMark, 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, VxMark, 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.

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.

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.

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, VxMark, 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.

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.

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 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, VxMark, 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.

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.

Configuration and Authentication Process

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.

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).

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 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.

  3. 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.

  4. 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.

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.

Code Links

Refer to the following code links for more details:

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, VxMark, 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:

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.

Code Links

Refer to the following code links for more details:

Tally reports
Election Results Reporting CDF
Ballot count reports

See

See the relevant

See the relevant

See the relevant

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 .

If interpretation didn't work, one possibility is that the ballot is actually a , 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.

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.

The vast majority of the VxMark hardware is the Ballot 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 or in the separately provided Los Angeles County documentation.

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 .

User Manual Reference:

User Manual Reference:

User Manual Reference:

User Manual Reference:

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).

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:

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 structure to accomplish this efficiently.

CVR ID Prefix 1
CVR ID Prefix 2
CVR ID
Hash

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 .

— CVR hashing logic, including the Merkle tree implementation

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

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.

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.

The recommended access control policy by role for system administrator, election manager, and poll worker cards is documented in the user manual (). 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.

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 .

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 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.

— VxSuite authentication lib, a good starting point for all things authentication

— High-level authentication state management for VxAdmin and VxCentralScan

— 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

— VxSuite authentication lib, a good starting point for all things authentication

— Artifact authentication logic

— OpenSSL commands underlying various authentication and signing operations

PCSC lite
CUPS
SANE
build system package inventory
lock file
lock file
lock file
hand marked ballot
machine marked ballot
VSAP (Voting Solutions for All People)
the documentation repository
<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

-

-

-

Root hash

4

-

-

4 hash

4

4d

-

4d hash

4

4d

4d6a9dad-e6d6-4a29-89bc-9ab915012b73

4d6a9dad-e6d6-4a29-89bc-9ab915012b73 hash

…

<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",
  ...
}
System Security Architecture
Physical Security
Procedural and Operational Security
Audit Procedure
Logging
Vulnerability Management
Risk Assessment
Hardware Criticality and Supplier Analysis
Cast Vote Records
Cryptography

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:

  • 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

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.

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.

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.

  • 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.

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

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.

  • the VxScan case is closed and sealed.

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.

During an Election

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

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

  • the poll-worker access door on the VxScan is sealed shut

All seal numbers should be recorded.

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).

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.

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.

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.

Physical Security

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

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.

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.

  • 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

  • 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.

  • 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.

VxMark

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

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

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

  • VxMark 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.

  • VxMark 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.

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.

Software Installation

Software installation involves two steps:

  1. Generating software images via Trusted Build: Trusted Build

  2. Imaging machines with those images: Imaging Machines

https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/backend/src/cast_vote_records/file_system_utils.ts
Merkle tree
compromised or faulty USB drives
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/cast_vote_record_hashes.ts
dm-verity
Access Control
Smart Cards and User Roles
https://www.iana.org/assignments/enterprise-numbers/?q=59817
https://github.com/votingworks/vxsuite/tree/v4.0.0-release-branch/libs/auth
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/dipped_smart_card_auth.ts
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/inserted_smart_card_auth.ts
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/java_card.ts
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/certs.ts
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/cryptography.ts
https://github.com/votingworks/vxsuite-complete-system/blob/v4.0.0-rc2/config/vendor-functions/basic-configuration.sh
https://github.com/votingworks/vxsuite/tree/v4.0.0-release-branch/libs/auth#scripts
https://github.com/votingworks/openfips201
https://github.com/votingworks/vxsuite/tree/v4.0.0-release-branch/libs/auth
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/artifact_authentication.ts
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/cryptography.ts
Smart Card Programming

Cryptography

Cryptographic Modules

VxSuite v4 contains four distinct cryptographic modules:

  • Smart cards

  • VxAdmin / VxCentralScan TPM (same underlying hardware)

  • VxMark TPM

  • VxScan TPM

  • OpenSSL software

All of the above are FIPS-compliant.

Smart Cards

VxAdmin / VxCentralScan TPM

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

VxMark TPM

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

VxScan TPM

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

OpenSSL

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.

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.

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.

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.

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.

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:

# 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

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.

Narrow Superuser Functions

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.

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.

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:

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

  • The network stack is disabled in the BIOS.

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

  • Ethernet ports are blocked.

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

Vulnerability Management

Vulnerability Disclosure Policy

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.

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

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.

Common Platform Enumeration (CPE)

This only indicates that a particular Nessus plugin is running to determine platform properties.

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.

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.

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.

Application Log Events

  • 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.

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

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.

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:

/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

Default VotingWorks Log Format

{
    "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",
}

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 theApplication Log Events fields.

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

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"

  • VxMark -> "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

Event.Id

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

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.

15.1-D Logging Event Types Table

General System Functions

System Event
Detail
Logging Details

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

VxMark 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: "cover_open"

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 VxMark, 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

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 printer-print-complete paper-handler-state-machine-transition With a failure Disposition

Critical system status messages

Detection or remediation of malware or other malicious software

Critical system status messages

Cryptographic boot validation success/failure

dmverity-boot with success or failure indicated by the Disposition

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

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 or restart. If followed by a machine-shutdown-complete log, the shutdown or restart can be taken to be successful. Otherwise, it can be considered abnormal. In the case of a restart, we additionally expect a machine-boot-init and machine-boot-complete log.

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.

For the file system as a whole, a failed integrity check will result in a dm-verity log with a failure Disposition.

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-destroy-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-complete logs.

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 readiness results

System pass or fail of hardware and software test for system readiness

diagnostic-init diagnostic-complete diagnostic-error 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

System readiness results

Pass or fail of ballot style compatibility and integrity tes

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

The toggled-test-mode log with a success Disposition indicates a pass. The toggled-test-mode log with a failure disposition indicates a fail.

System readiness results

Zero totals of data paths and memory locations for vote recording

The polls-opened log with a success Disposition indicates a pass. The polls-opened log with a failure Disposition and User prevented from opening polls because ballots have already been scanned in the body indicates a fail.

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 VxMark 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.

Authentication and Access Control

System Event
Detail
Logging Details

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

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)

sudo-action

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.

Networking

System Event
Logging Details

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.

Software

System Event
Detail
Logging Details

Installing, upgrading, patching, or modifying software or firmware

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

For lower-level hardware daemons, we have process-started and process-terminated logs.

Abnormal process exits

unknown-error

Successful and failed database connection attempts (if a database is used)

database-connect-init database-connect-complete

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 Functions

System Event
Detail
Logging Details

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

Voting events

Casting a vote

VxMark: 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

VxMark: ballot-invalidated VxScan: scanner-state-machine-event with event reject

Voting events

Success or failure of log and election results exportation

export-cast-vote-record-complete file-saved

Audit Procedure

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

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. 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.

  2. export CVRs from all the VxCentralScan's

  3. use VxAdmin to aggregate CVRs, adjudicate write-ins, and generate final tallies

  4. aggregate tallies and CVRs at the audit jurisdiction level, most often the State

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

  6. the RLA tool will generate a sample of ballots to audit

  7. retrieve the selected ballots by batch ID and sequence number

  8. enter the interpretation of those ballots into the RLA tool

  9. 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.

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

  4. use VxAdmin to aggregate CVRs, adjudicate write-ins, and generate final tallies

  5. produce ballot counts by scanner and by batch on VxAdmin – these are effectively contest totals by batch files in auditing language.

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

  7. input tallies and ballot manifests into the RLA tool

  8. the RLA tool will generate a sample of batches to audit

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

  10. enter the hand-count batch tallies into the RLA tool

  11. 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.

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

Trusted Build

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, VxMark, 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.

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.

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.

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.

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. This hash will be provided to SLI/EAC for official verification of the image.

Note: The vxmark VM currently requires a slightly modified process. For vxmark, VotingWorks will boot the VM, change the vendor password, then shut the VM down. After verifying it is not in a running state, VotingWorks will boot the VM again and complete the rest of the process as previously described.

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:

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.

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)

  • Audio Clips (audioClips.jsonl)

  • System Settings (systemSettings.json)

  • Metadata (metadata.json)

Election Definition

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

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 VxMark there is a button labelled, by default, "Start Voting." If the voter has set VxMark 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 app strings file is optional. If not provided, default English strings will be used.

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.

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- 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 tabulators to consider it a mark.

    • 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.

    • 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.

    • castVoteRecordsIncludeOriginalSnapshots - When set to true, scanners will include "original" snapshots in the CVR export for each ballot. This includes extra information about the marks on the ballot before contest rules are applied as specified in the CVR CDF. This extra information increases the size of the CVR export, degrading performance.

    • 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.

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

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.

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 VxMark 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.

Installing Debian 12 on VxBuild

Creating a Debian 12 USB Install Drive

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.

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".

  4. Leave the proxy information blank and click "Continue".

  5. You will be asked to configure "popularity-contest". Select "No" and click "Continue".

  6. The installation process will continue. Once it completes, you will be presented with a final screen confirming that it was successful.

  7. Remove the USB drive and click "Continue".

  8. The system will reboot and automatically start Debian 12.

  9. Log in with the "vx" user and password you created during the installation process.

  10. Several basic configuration prompts will be displayed. Select "Next".

  11. Select your keyboard preference and click "Next".

  12. Turn off Location Services and click "Next".

  13. Do not configure any online accounts. Select "Skip".

  14. Click the "Start Using Debian GNU/Linux" button. The dialog will be closed.

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.

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 VM.

  2. Press the start button ▶️.

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

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

  5. 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:

Final Configuration

We'll now clone the offline VM to prepare images for specific machine types, i.e., VxAdmin, VxCentralScan, VxMark, 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, vxmark, and vxscan.

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

  • 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. Once the VM has initialized, log in with username vx and password votingworks.

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

  5. 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 white screen displaying “Card Reader Not Detected”. In the VM menu, select "Virtual Machine" > "Shut Down" > "Shut Down". Close the VM window once shutdown is complete.

Virt Manager - Network Access & Troubleshooting

Disabling Network Access

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.

Any VM cloned from this offline VM will also have a disabled network since those settings are inherited from the original VM.

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.

Build Machine Configuration

Build Machine Requirements

  • Operating system: Debian 12

  • RAM: 8GB minimum

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

  • Storage: 250GB minimum

Build Machine Configuration

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:

Online Phase

  1. Open virt-manager:

  1. Double-click the online VM.

  2. Press the start button ▶️.

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

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

  5. 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:

System Overview

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

  • VxAdmin: election setup and election results manager

  • VxMark: ballot-marking device (BMD)

  • VxScan: precinct scanner

  • VxCentralScan: batch scanner

VxAdmin

VxMark

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.

VxScan

VxCentralScan

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.

Ballot Definition CDF

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

Required Class Attributes

Restricted Enums

Ignored Classes and Enums

Ignored Class Attributes

VxSuite CDF Conversion

Attribute Mappings

Translations

Geographies

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

VxSuite CDF Limitations

  • 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 VxMark (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.

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

VxSuite v4 uses NXP JCOP 4 Java Cards, specifically this model: .

These smart cards are FIPS140-2-certified: .

The applet that we run on the cards, , 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.

This chip is FIPS140-2-certified: .

This chip is FIPS140-2-certified: .

This chip is FIPS140-2-certified: .

We use OpenSSL 3.0.9 and install the FIPS provider, per . 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: .

FIPS compliance via software modules: For all other operations, OpenSSL uses the FIPS provider. Our guarantees this.

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 .

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

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

VotingWorks' vulnerability disclosure policy is publicly available here:

VxSuite applications use a 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 is a status update or an action, and whether it originated with the user, application, or larger system. The full list of log event types with descriptions is included in the automatically generated log .

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.

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:

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 and will present a dm-verity failure message. dm-verity with a failure Disposition

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 and diagnostic-error logs.

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 , 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.

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

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.

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 .

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 .

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 VxMark. The 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 VxMark.

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 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 .

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

You will now need to perform the 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 .

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 .

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, .

Using VxSuite for an election begins with generating an and using an external system.

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 . Once configured, VxAdmin is used for two key election setup tasks:

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

Programming 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 tabulate cast vote records from the scanners. The results are available for review or export in . Once tabulation is complete, election administrators can mark results as official, after which no new results can be added.

VxMark 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 from VxAdmin. Once configured, a voter can make vote selections in various interaction modes according to their needs.

After the voter finishes their vote selections, VxMark prints a 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 and tabulated at one of the system's scanners.

VxScan is the system's precinct scanner. At the beginning of an election, it is configured with an 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 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 to an attached USB drive.

If the election is 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 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.

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 from VxAdmin. The election package specifies the ballot layouts.

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

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 .

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

CDF Class
VxSuite Attribute Requirements
CDF Enum
Allowed Values
CDF Entity
CDF Class
Ignored Attributes

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

Ballot Definition CDF Attribute
VxSuite Election Definition Attribute

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.

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 .

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:

https://www.cardlogix.com/product/nxp-jcop-4-java-card-3-0-5-classic
https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3746
OpenFIPS201
https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4411
https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/2959
https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3492
these instructions
https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4282
OpenSSL config
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/usb-drive/scripts/mount.sh
these lines in the setup-machine.sh
firewall configuration
https://github.com/votingworks/vxsuite/security/policy
shared logging library
documentation
documentation
here
sudo su -
/home/vx/code/vxsuite-build-system/scripts/sb-unsigned-upload.sh vxadmin
sudo /home/vx/code/vxsuite-build-system/scripts/sb-unsigned-download.sh vxadmin
sudo /home/vx/code/vxsuite-build-system/scripts/sb-signed-upload.sh vxadmin
sudo su -
/home/vx/code/vxsuite-build-system/scripts/sb-signed-download.sh vxadmin
{
  "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,
    "writeInTextArea": 0.05
  },
  "centralScanAdjudicationReasons": [],
  "precinctScanAdjudicationReasons": [],
  "disallowCastingOvervotes": false,
  "allowOfficialBallotsInTestMode": false,
  "precinctScanEnableShoeshineMode": false,
  "castVoteRecordsIncludeOriginalSnapshots": false,
  "castVoteRecordsIncludeRedundantMetadata": false,
  "disableVerticalStreakDetection": false
}
{
  "version": "latest"
}
ballot hash
ballot hash
ballot hash
ballot hash and election package hash
ballot hash
ballot hash
election package
system settings
system settings
election package
system settings
system settings
app strings
system settings
election definition
election package
app strings
audio files
system settings
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
cd ~/code/vxsuite-build-system
./scripts/tb-create-offline-vm.sh
sudo virt-manager
ping -c2 google.com
cd ~/code/vxsuite-build-system
./scripts/tb-run-offline-phase.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. VxMark
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 virsh net-start default
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 virsh list --all
sudo virt-manager
mkdir ~/code && cd ~/code
git clone https://github.com/votingworks/vxsuite-build-system
cd ~/code/vxsuite-build-system
./scripts/tb-run-online-phase.sh <inventory-name> 
sudo shutdown -h now

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

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

ElectionType

general, primary

ReportingUnitType

county, precinct, split-precinct, state, other

ActivationContest

ActivationOption

AnnotatedString

AnnotatedUri

BallotMeasureType

CandidatePreElectionStatus

Coalition

ContactInformation

DayType

ElectionAdministration

GeoSpatialFormat

Hours

LatLng

OfficeGroup

OfficeTermType

OrderedHeader

PartyContest

PartyOption

PartyPreferenceContest

PartyRegistration

Person

RetentionContest

Schedule

ShortString

SpatialDimension

SpatialExtent

StraightPartyContest

StraightPartyRuleset

TimeWithZone

VoteVariation

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

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

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

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

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.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

Signed Hash Validation
Signed Hash Validation
Verifying the Image Installed on a Machine
VxAdmin Function
VxAdmin & VxCentralScan Hardware
VxMark Function
VxMark Hardware
VxScan Function
VxScan Hardware
VxCentralScan Function
VxAdmin & VxCentralScan Hardware
Imprinting
Quality Assurance Protocols – Software
10114
45590
54615
86420
43111
24260
56877
11219
19506
11936
22964
25220
10287
10386
10302
System Integrity
online
offline
final configuration
virt-manager
Secure Boot Signing
digital signature
VxSuite Election Definition
Ballot Definition CDF
IETF language tags
app strings catalog
latest Debian release
Secure Boot Signing
Imaging Machines
playbooks/virtmanager/clone-base-vm.yaml
Installing Debian 12 on VxBuild
vxsuite-build-system
election package
hand marked ballots
election package
digital signature
role-based smart cards
several results formats
election package
machine marked ballot
election package
a tally report
cast vote records
polls closed report
election package
cast vote records
accessed on their website
JSON schema in the vxsuite repository
original NIST schema
VxSuite Election Definition
VxSuite Election Definition
configured to support second-chance voting
ballot strings
Election
Precinct
District
CSV format
CSV format
Configure VxAdmin
Save Election Package
Configure VxCentralScan
#scan-ballot-batches
#adjudicate-ballots
#saving-cast-vote-records-cvrs
Printer Management
Scanner Management
Configure VxScan
Opening Polls
Closing Polls
Additional Poll Worker Actions
Assisting Voters
#saving-cvrs
Smart Cards and User Roles
USB Formatting
Tally Results
Write-In Adjudication
Manual Tallies
Reports
Setting Date & Time
Configure VxMark
Open and Close Polls
Voting Sessions
Voting Session Language & Settings
VxMark Hardware Setup
VxAdmin Diagnostics
VxCentralScan Diagnostics
VxScan Diagnostics
VxMark Diagnostics
VxScan Diagnostics
VxCentralScan Diagnostics
VxAdmin Error Messages
VxCentralScan Error Messages
VxMark Error Messages
VxScan Error Messages

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 both the vx-iso and image USB drives into the system. If this is a VxMark 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. The precinct system components (VxMark and VxScan) are to auto-boot from a bootable USB drive when connected and should auto-boot to vx-iso.

    2. The central system components (VxAdmin and VxCentralScan) require entering f9 after powering on to boot to USB. Select the USB drive corresponding to the vx-iso drive.

  4. Select "Write an image". You can navigate vx-iso with the keyboard. This option will be auto-selected in 10 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 images on the image USB drive will be displayed. Select the number that identifies the correct image.

  7. Enter 27 for the final expected size of the image in GB.

  8. Confirm your selections and wait for imaging to complete.

  9. Once imaging completes, remove the USB drives and press "Enter" to reboot.

  10. On reboot, you should see a prompt for a passphrase. This passphrase is used to decrypt the machine's /var partition so that it can be re-encrypted via the TPM. Enter "insecure" — this passphrase is not relevant to our security architecture. If Secure Boot is not enabled, you'll instead see a note about needing to enable Secure Boot. The machine will auto-boot you into the BIOS. On reboot after that, you should see the passphrase prompt.

VxMark Boot Order Fix

On VxMark, if you find yourself on an unexpected screen after the above steps, e.g., a Secure Boot error screen or booting straight into a previously installed image, you may need to manually edit the VxMark boot order. You can follow these instructions to do so:

  1. Power off the machine.

  2. Insert the vx-iso USB drive.

  3. Power on the machine and auto-boot to vx-iso.

  4. Use "Ctrl+C" to leave the main vx-iso interface and access a terminal.

  5. Type efibootmgr to list out the boot entries. The output will look something like this:

BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0000,0001,0002
Boot0000* USB HDD
Boot0001* vxadmin - Installed 20241030 
Boot0002* vxadmin-signed - Installed 20241031
  1. Identify the boot entry for the recently installed image. Let's say in this case we want vxadmin-signed, Boot0002.

  2. Run the following command, replacing the index, to make that entry the first in the boot order after the USB drive:

efibootmgr -o 0002

Imaging Machines

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

Verifying the Image Installed on a Machine

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.

Note: In some 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:

echo HASH | xxd -r -p | base64

CSV Exports

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

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:

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
Header
Values

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

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.

Ballot Count Report CSV Structure

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

BMD

The count of machine marked ballots

HMPB

The count of hand marked paper ballots. In a multi-sheet election, this is just the count of the first sheet

HMPB Sheet {N}

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

Manual

The count of manually entered ballots

Total

The total ballot count

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

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"

Scanner ID

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

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

Header
Value

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

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.

Audio Visual & Display Screen Settings

Electronic Display Screen Specifications

The voting system features three electronic display screens - on VxScan, on VxMark, 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)

  • 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

VxMark

15.6"

1080 x 1920

700:1

220 nits

Central Laptops

14"

1920 x 1200

1,330:1

300 nits

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

VxMark

Report Available on Request

Central Laptops

Audio-Visual Settings

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

  • VxMark Function > Display Formats & Interaction Modes

  • VxScan Function > Visual Settings

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.

Quality Assurance Protocols – Software

Automated Unit Tests

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.

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.

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.

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.

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.

Safe Concurrency (2.5-B)

VxSuite practices safe concurrency by using programming languages that, in their design, avoid the most common dangers of 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.

Quality Assurance Protocols – Hardware

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.

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.

Assembly (Protocol & Detailed Instructions)

Quality Assurance Protocols – Integration Testing

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:

Production Unit Quality Assurance

Usability & Accessibility

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:

  • 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.

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

Usability and Accessibility Testing Reports

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//shv// 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:

  • 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.

Code Links

Refer to the following code links for more details:

The /var partition should encrypt and expand, and you should then find yourself in . Proceed to that section.

This section walks through the steps to install a Trusted Build image on a VotingWorks component using .

See for details.

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

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 other fields are standard fields:

VotingWorks code has extensive unit test coverage. All libraries in the 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.

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

To organize this process, we make use of checklists. A base set of checklists can be viewed here: . 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.

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 .

Performance-critical parts of the application, like image processing for ballot interpretation, are written in . 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 () 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.

Our complete assembly work plans are available .

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, VxMark, VxScan, and VxCentralScan are public .

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

Because the TPM private key will only sign data if the system hash is correct, per , we can further be confident that the software on the machine is authentic and unmodified.

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

Basic Configuration Wizard
vx-iso
Signed Hash Validation
printed ballot count reports
vxsuite repository
here
Software QA Checklists
well-tested
Rust
2024 Report
in the document repository
external testing reports
internal testing reports
here in the documentation repository
VotingWorks Pollworker Testing Report VxSuite
VotingWorks UAT Report VxSuite
metadata fields
metadata fields
message = 1//shv//<system-hash>#<software-version>#<election-id>#<current-timestamp>
qrCode  = <message>;signature(<message>);<machine-cert>
System Integrity

Public Documents

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

  • Election Event Log Coding: Logging

  • CDF Implementation:

    • Ballot Definition: Ballot Definition CDF

    • Cast Vote Records: Cast Vote Records

    • Election Results Reporting: CDF ERR Export

    • Logging: Logging

  • Barcodes:

    • Hand Marked QR Code: Hand Marked Ballots

    • BMD Summary Ballot QR Code:Machine Marked Ballots

    • Signed Hash Validation QR Code: Signed Hash Validation

  • Audit Implementation: Audit Procedure

UL 62368-1 Test Report
UL 62368-1 certified
https://check.voting.works
https://check.voting.works
https://github.com/votingworks/vxsuite/blob/v4.0.0-release-branch/libs/auth/src/signed_hash_validation.ts

Warranty Model

Estimated Replacement Rates

VxScan (incl ballot box)

VxAdmin

VxCentralScan

VxMark

Estimated Replacement Rate

10 years

10 years

10 years

10 years

Estimated Cost Per Replacement

$7,500*

$2,500*

$2,500*

$7,500*

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

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.

Associated Replacement Policies, Services, and Available Maintenance Agreements

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.

A sample TRUST Services Agreement is available .

here

Hardware Criticality and Supplier Analysis

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.

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.

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.

Other Considerations

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.

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.

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.

  • VxAdmin & VxCentralScan Hardware

  • VxScan Hardware

  • VxMark Hardware

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

Supply Chain Risk Management Strategy

Using the criteria described above, the VotingWorks operations team narrows down the list of 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.

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:

  • Access Control

  • Artifact Authentication

  • System Integrity

  • Networking

  • Password and Credential Policies

  • Defense-in-Depth and Least Privilege

  • Cryptography

  • Procedural and Operational Security

  • Trusted Build

Please also refer to the VxSuite User Manual - v4, notably the Setup Inspection documentation.

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
VxMark ballot
Parts of a VxMark ballot
English/Chinese VxMark ballot
Election Entity Relationship Diagram
Relationship of grid layouts to other entities in the election definition
Polls opened report for a primary election
Polls closed report for a general election in test ballot mode
Voting paused report
Voting resumed report
Full election tally report
Full election results grouped by voting method
Tally report with a complex filter
Before adjudication
Adjudication just started
Adjudication almost finished
Full write-in adjudication report
Write-in adjudication contest results
Ballot count report grouped by precinct and voting method
Complex filter specified by attribute
Laptop keyboard and screen
Laptop ports
VxAdmin fully connected with mouse, hub, charger, USB cable, and printer
VxCentralScan fully connected with mouse, hub, charger, USB cable, scanner (fi-8170), and power backup
Application architecture diagram
Ballot box front, collapsed
Ballot box side, collapsed
Ballot box lid underside, collapsed
Ballot box side, open
Ballot box interior
Ballot box side, closed
Ballot box from above, closed
Ballot box with scanner installed
Scanner rear
Scanner main bottom tub
Scanner upper tub
Poll worker door area
Poll worker door sealed
Access door area
Scanner features
VxScan Wiring Diagram
Wiring components
Voltage warning over power supplies
Bottom left panel seal
Bottom right panel seal
Top panel seal
Vertical streak detected
No vertical streak detected
All shapes
Timing mark shapes
Timing mark shapes along edges
Timing mark grid
QR code search
Correctly oriented ballot
Ballot bubble scores
Valid Marks
Invalid Marks
Identifying contest options
Scoring write-in areas
Accessible Controller
Smart card insert
Power controls
BMD case fully packed and padded
Peripherals case fully packed
Peripherals case with privacy shield removed
Peripherals unpacked
Passed
Failed
Top level system diagram
Formatted version of the above CSV excerpt
Formatted version of the above CSV excerpt

[PDF]

[Excel]

Risk Assessment
Risk Assessment

Basic Configuration Wizard

After you've imaged a machine, the machine will boot into a basic configuration wizard. The majority of the steps are self-explanatory, but "Step 1: Set Machine ID" and "Step 4: Create Machine Cert" require some extra clarification.

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.

Creating Machine Cert

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

Enter a jurisdiction ({state-2-letter-abbreviation}.{county-town-etc}, e.g., ca.los-angeles or vx.test for test/demo machines):

SLI should use co.sli

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

Insert a USB drive into the machine. Press enter once you've done so.

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:

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.

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.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.pem" file and send the certificate back to you, in the form of a "cert.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.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.

Hash/Checksum Verification of Dependencies

APT

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

RubyGems

Rust

Cargo

Node

npm

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

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.

Preparing USB Drives for Imaging

To install an image on a VotingWorks component, i.e., to image a machine, you need two USB drives:

  • An image USB drive — This is an empty USB drive with two partitions, a "Data" partition that can contain as many VotingWorks images as space allows and a "Keys" partition that can optionally contain the 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/sdXwith the appropriate path to the USB you are using, e.g. /dev/sda

sudo dd if=/dev/zero of=/dev/sdX bs=8M && sudo sync

Drives provided by VotingWorks are also initialized with this process. If you have existing drives that were zeroed out and are properly partitioned, you can skip these steps and simply copy a VotingWorks image file directly to the USB. Those instructions can be found at the bottom of this page in the Copying an image file to a previously configured USB drive section.

Clone the vx-iso repo for the tooling necessary to prepare the above:

git clone https://github.com/votingworks/vx-iso.git
cd vx-iso

If this is SLI, we have provided you with vx-iso USB drives so that you don't need to prepare them from scratch.

You'll need access to the relevant images and optionally the VotingWorks Secure Boot public keys. Both of these are stored on a private S3 bucket, though they're not sensitive, and VotingWorks can prepare temporary links to grant access to them.

If this is SLI, you do not need to create data drives with the VotingWorks Secure Boot public keys. Secure Boot has already been configured on all your machines.

Copying an image file to a previously configured 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:

/media/vx/Data

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

ls /media/vx/Data/

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:

~root/vxadmin-signed.img.lz4

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

sudo cp ~root/vxadmin-signed.img.lz4 && sudo sync

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 USB drives and VotingWorks image files as required.

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

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.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.

The VotingWorks build system, , 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 . These tools are defined within the for each release of VotingWorks applications, and only those tools are installed during builds.

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

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: .

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: .

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 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 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: .

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: .

A vx-iso USB drive — is our VotingWorks-specific ISO installer program.

to create a vx-iso and/or image USB drive.

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 documentation, specific to each VotingWorks application release.

vxsuite-build-system
here
vxsuite-build-system
SecureApt
pip: Secure installs
tb-install-ansible.sh
Debian 12 x86 pip requirements
FPM 1.15.1
rubygems.yaml
rust.yaml
Cargo.toml vs. Cargo.lock
node.yaml
node.yaml
vx-iso
Follow these instructions
Hash/Checksum Verification of Dependencies