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...
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.
Requirement 14.1-C.1 – the use of cryptography to secure VxSuite – is covered by
the certificates and signatures used by smartcards, see Access Control / Smartcard Keys and Certificates.
digital signatures applied to all files exchanged between system components, see Artifact Authentication.
hard-drive partition hashes, as well as kernel and bootloader signature, used as part of secure-boot, see System Integrity.
additional details on encryption vs. authentication and the type and size of cryptographic keys we use is provided in Cryptography
Requirement 14.1-C.2 – the use of malware protection to secure VxSuite – is covered by the secure boot and safe mounting of external drives covered in System Integrity.
Requirement 14.1-C.3 – the use of a firewall to secure VxSuite – is covered in Networking.
Requirement 14.1-C.4 – the use of system configurations to secure VxSuite – is covered by:
aspects of secure-boot as described in System Integrity.
Requirement 11.4-A – on least privilege – is covered by Defense in Depth and Least Privilege.
Requirements 13.3-A, 13.3-C, 13.3-D are covered by Cryptography
All VxSuite components are blocked from connecting to any network. Thus, there is no network in a VxSuite implementation. Our network design is secure by virtue of it being completely absent.
We ensure that VxSuite components cannot connect to a network, either wifi, bluetooth, or ethernet. This is achieved through a few layers of defense:
Networking manager is turned off and removed in the setup process. See vxsuite-complete-system/setup-machine.sh
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 BIOS is configured to disallow network connections.
Wifi/bluetooth hardware is not present on the machines.
On VxSuite machines, there are no passwords for election administrators to use – only smart cards as described above. 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.
This section maps to Requirement 9.1.1-A.2
VxSuite provides software independence through a paper ballot based voting system:
Voters mark pre-printed paper ballots by hand. Since no software is involved, this phase is naturally software independent.
Ballot scanners, both precinct and batch, produce cast-vote records (CVRs) that are suitable for running post-election audits. Thus, if software on VxSuite scanners is modified in such a way as to affect the way ballots are interpreted, a post-election audit, such as a risk-limiting audit, can be used on the produced cast-vote records to ensure that the outcome is true to the intent of the voters as recorded on the paper.
This section maps to Requirement 14.1-D
VxSuite can be operated securely by 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.
VxSuite should be used only with sanctioned equipment and peripherals.
do not connect USB devices of unknown source to any VxSuite component.
do not connect any USB device to VxSuite ports other than those explicitly sanctioned in this documentation.
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 a numbered seal through the appropriate hole, preventing the case from being opened without breaking the seal.
VxCentralScan laptop and peripherals should be kept in their case, with a numbered seal through the appropriate hole, preventing the case from being opened without breaking the seal.
The Fujitsu 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.
VxScan should be kept closed with a numbered seal through the appropriate hole, preventing the case from being opened without breaking the seal.
VxAdmin, VxCentralScan, VxScan, and the Fujitsu 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 smartcards should be kept in a safe or locked drawer, separately from VxAdmin. The PIN for the system admin smartcard, if recorded on paper, should also be kept locked separate from both VxAdmin and the card.
It is a good practice, every year or so, to reset the PIN on the system administrator cards. This can be done using the VxAdmin laptop.
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 smartcards.
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 live 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.
Ensure that seals on equipment are untouched and appropriately numbered since L&A.
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 sealed to the box
the poll-worker access door on the VxScan is sealed shut
All seal numbers should be recorded.
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, record the seal number before opening, and ensure the poll worker door is resealed afterwards, recording the new seal number.
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 smartcard PIN is entered via the keyboard, and not via the mouse.
Unsealing the poll worker door is required to close the polls. 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.
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.
Now that you have the vx-iso and vx-data USB drives ready, it’s time to write the image to hardware.
Insert both USB drives into the system. For VxScan, you'll need to use the USB hub provided by VotingWorks.
For VxScan only, attach the USB hub to the hardware device to be imaged.
Boot into the system BIOS. For VxAdmin and VxCentralScan, the F12 key will take you to the boot menu. For VxScan, the Del key will take you to the BIOS. After entering the BIOS password, navigate to the Boot menu.
In the appropriate menu, select to boot from USB, and choose the vx-iso USB drive (Samsung Flash Drive).
You will be rebooted into a minimal system with a menu of options. By default, it will initiate the process for writing an image after several seconds. You can stop this by simply pressing an up or down arrow key.
If you do interrupt the automatic menu selection, you will need to select “Write an image”
The image should be automatically detected. If not, you can select it from the menu of available images.
You will be asked to enter the final size of the image. Please enter the value provided by VotingWorks: 110 (do not include a specific unit such as GB)
A final confirmation prompt describing the image to copy and the disk to copy to will appear. If it is correct, answer “y” to continue.
A progress bar showing the status of the copy will be displayed. Once the copy completes, press Enter to reboot.
The system will reboot to the BIOS. Exit the BIOS. (This step will be removed in future builds.)
Once the system has rebooted, you will need to configure and certify it. To do that, please see: "Machine Configuration Wizard and VxCertifier."
Once an image has been installed and configured, you can verify the hash against what was built and signed during the Trusted Build process. To perform this verification, you will need the vx-iso USB drive and the hash of the image.
First, be sure the system is powered off. The simplest way to do this if the machine is running is by pressing the power button.
Once the machine is powered off, insert the vx-iso USB drive.
Power the system back on and be ready to interrupt the boot process. On vxadmin and vxcentralscan laptops, this should be the F12 key. On vxscan, you will need to use the Del key.
For vxadmin and vxcentralscan, once you are in the Boot Menu, select the USB drive and press Enter.
For vxscan, once you are in the BIOS (you may need to enter the BIOS password), navigate to the Boot menu option, then select the USB drive to boot from.
After booting to the USB drive on any of the systems, you will be booted into a minimal menu. Using the arrow keys, navigate to the Verify Hash option and press Enter.
This will automatically calculate the hash of the installed image, and you can then compare it with the hash created during the Trusted Build process.
Once you have verified the hash, you can press Enter to reboot. Be sure to remove the vx-iso USB drive as well.
The VVSG 2.0 Test Assertions state that:
TA1.2-H 1: The voting system MUST prevent the loss of voting data in the event of a data input failure without relying on re-casting ballots. TA1.2-H 2: The voting system MUST prevent the loss of voting data in the event of a storage device failure without relying on re-casting ballots.
To meet these assertions, 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.
To perform continuous export while also keeping signatures, i.e. authenticity information, up-to-date, we have to be able to write both CVRs and authenticity information incrementally. (It isn’t enough to just hash and sign new data. We need an up-to-date root hash/signature.) We can use a Merkle tree structure to accomplish this efficiently.
Assuming every CVR has a random UUID, e.g. 4d6a9dad-e6d6-4a29-89bc-9ab915012b73, we can specifically use the following structure:
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.
-
-
-
Root hash
4
-
-
4 hash
4
4d
-
4d hash
4
4d
4d6a9dad-e6d6-4a29-89bc-9ab915012b73
4d6a9dad-e6d6-4a29-89bc-9ab915012b73 hash
…
Then on the USB, we can use a flat structure that’s much easier to reason about and iterate over:
The database table makes recomputing hashes easy, as retrieval of all hashes for a given ID prefix becomes a simple SQL query. This approach also decreases the chance that we accidentally depend on data written to USB when computing hashes, protecting against compromised or faulty USBs.
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:
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.
Refer to the following codebase links for more detail on CVR hashing:
https://github.com/votingworks/vxsuite/blob/main/libs/auth/src/cast_vote_record_hashes.ts — CVR hashing logic, including the Merkle tree implementation
The foundation of our system integrity solution is the TPM (described in greater detail under Private Key Storage).
Our design for system integrity maps closely to that of ChromeOS:
The hard drive is partitioned such that executable code lives on read-only partitions, and only /var
and /home
are mounted read/write for configuration, logs, and working data like scanned ballot images.
The read-only partitions are verified by dm-verity, which generates a hash tree of all the raw partition blocks, culminating in a single hash root for the entire read-only filesystem.
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.
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.
The private key described previously in Access Control is generated in the TPM and bound to Platform Configuration Registers (PCRs) that include the BIOS, the secure boot public keys, and the bootloader+kernel+command-line. Thus, this private key is only usable if the machine boots appropriately sanctioned source code with a hard drive whose read-only partitions are unmodified.
As a diagram:
The integrity of the overall system is ensured because:
Any change in the executable portion of the hard drive will be detected when dm-verity checks the hard drive blocks against its stored hashes.
Any change in the hashes stored on disk will be detected against the mismatched root hash, present in the kernel boot command line.
Any live changes to the hard 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.
Our system is configured so that all partitions other than /var
, /tmp
, and /home
are mounted as 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
.
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.
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.
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.
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:
To authenticate “ballot packages” — These configuration bundles are exported by VxAdmin and used to configure VxCentralScan and VxScan.
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 (as configured in ):
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, extracts the exporting/signing machine’s public key from its certificate as provided in the .vxsig file, reconstructs the message, and then verifies the signature. The importing machine also importantly verifies that the signing machine certificate in the .vxsig file is a valid certificate that is 1) signed by VotingWorks and 2) for the expected machine given the artifact type, e.g. VxAdmin if the artifact is a ballot package. We verify 1 using the VotingWorks CA certificate installed on every machine.
If signature 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.
Refer to the following codebase links for more detail on VxSuite artfiact authentication:
— VxSuite authentication lib, a good starting point for all things authentication
— Artifact authentication logic
— OpenSSL commands underlying various authentication and signing operations
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.
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.
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.
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
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.
All processes that a user can directly interact with in VxSuite run as user vx-ui
. The processes that access the smartcard 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.
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 stick with a timestamp, the order of CVRs is obviously preserved on the USB stick, 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.
The exact procedure used by VxScan, rather than just a mv
operation, is three steps. This is done to ensure that all metadata for a given CVR is updated, including file creation time. 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. Thus, the operations VxScan performs to move a single CVR "up to the top of the pile" is made up of three parts:
first, rename the directory corresponding to the CVR to a new name that indicates it is being copied, specifically by appending -old:
mv 4d6a9dad-e6d6-4a29-89bc-9ab915012b73/ 4d6a9dad-e6d6-4a29-89bc-9ab915012b73-old/
then, copy this renamed directory back to the original name:
cp -r 4d6a9dad-e6d6-4a29-89bc-9ab915012b73-old/ 4d6a9dad-e6d6-4a29-89bc-9ab915012b73/
finally, delete the -old directory:
rm -r 4d6a9dad-e6d6-4a29-89bc-9ab915012b73-old/
This three-step operation ensures that
all metadata for that CVR 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.
VxSuite is composed of individual machines, namely VxAdmin, VxCentralScan, and VxScan, as well as smartcards for authentication. Each machine and each smartcard 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 smartcard 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, VxScan machine, or smartcard. 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 as one VotingWorks component type cannot act like another, e.g. a VxScan cannot sign an election configuration package like a VxAdmin can.
VotingWorks further certifies every VxAdmin as bound to a particular jurisdiction, e.g. Warren County, Mississippi. This is important because VxAdmins program smartcards and should not be able to program cards for other jurisdictions.
Every smartcard, 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 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 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.
As described above, programmed smartcards 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 don’t certify the same card public key twice. 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 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 smartcards to be interoperable with other PIV systems.
We store our root VotingWorks certificate authority (CA) private key encrypted in a password vault, usable only by a few authorized engineers.
VxAdmin, VxCentralScan, 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 Java Cards, version 3.0.4. 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.
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.
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, scan, or card (the first three 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 = system-administrator, election-manager, poll-worker, or poll-worker-with-pin (system administrator and election manager cards always have PINs)
1.3.6.1.4.1.59817.4 — Election hash = The SHA-256 hash of the election definition
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
This means that a system administrator card will automatically expire after 5 years, and election manager and poll worker cards will automatically expire after 6 months.
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:
VotingWorks installs the appropriate security module code on the card.
VotingWorks instructs the smart card to generate a key pair and export the public key.
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:
VotingWorks machine code instructs the machine’s TPM to generate a key pair and export the public key.
VotingWorks machine code generates a certificate signing request (CSR) for that public key and writes the CSR to a USB.
On VxAdmin, VotingWorks additionally specifies a jurisdiction. That jurisdiction is included in the CSR.
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.
VxAdmin certificates are themselves CA certificates capable of creating additional certificates (necessary for smart card programming).
The USB is plugged back into the machine to be certified. The machine loads the certificate from the USB and saves it onto its hard drive.
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.
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:
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.
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.
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.
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.
VxAdmin also saves its own CA certificate onto the card (more on how this is used under Authentication).
Smart card authentication involves the following steps:
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.
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.
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.
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.
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.
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.
Refer to the following codebase links for more detail on VxSuite access control:
VxSuite v3.1 contains four distinct cryptographic modules:
Smartcards
VxScan TPM
VxAdmin / VxCentralScan TPM (they run on the same hardware)
OpenSSL software
VxSuite v3.1 uses NXP JCOP 3 smartcards, specifically this model:
These cards are FIPS140-2 certified:
A future version of VxSuite will support JCOP4 cards from NXP, which have a more recent FIPS compliance record:
The applet we run on the card, , 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 JavaCard operating system, implemented by the NXP JCOP card, which is FIPS140 compliant.
Asus uses a TPM2.0 chip by Nuvoton:
This chip is FIPS-compliant:
That CMVP requires Debian 11.5 (released September 2022). VxSuite v3.1 uses Debian 12 (released June 2023), in order to ensure a maximally patched operating system. OpenSSL on Debian12 does not yet have a FIPS-compliant certificate. That said, we use only FIPS-compliant algorithms (ECDSA), and we use OpenSSL in this software mode only for verification operations that do not require secret-key access.
VxSuite does not use encryption to secure data (CVRs, election definitions), 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 sticks are not encrypted, so they can be viewed using any computer. This is by design.
All digital signatures used to authenticate election definitions and CVRs are ECC 256-bit keys, specifically using the standard NIST P256 curve.
All hashes – used to generate election IDs and in the Merkle-tree hash of CVRs on the USB – are performed using the NIST standard SHA256.
System integrity on the drive, using dm-verity, is done using SHA256 hashes, and the code signing is done using RSA-4096 bit keys.
This document maps to the following requirements in VVSG 2.0:
3.1.4-A, E, F, G, and H
3.2-B and 3.2-B.1
3.2-D
3.2-E
The VotingWorks build process consists of three distinct build phases: , , and . The build process uses an inventory definition containing all the necessary information for a trusted build. All three phases are executed within a separate virtual machine (VM) managed by the tool, running on a Debian 12 operating system.
In the online phase, the build process utilizes a base Debian 12 VM with network access enabled. All necessary code repositories and build tools are securely retrieved and transferred to a USB for use during the offline phase.
In the offline phase, the build process utilizes a base Debian 12 VM with network access disabled. All necessary code repositories and build tools are transferred from the USB created during the online phase.
In the final configuration phase, the build process utilizes a clone of the offline VM to configure the specific VotingWorks application based on functionality: VxAdmin, VxCentralScan, VxScan, or VxMark.
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 and verification of the VotingWorks application created via the Trusted Build process.
For a final production image, an additional process is required to securely sign the installation image for use with Secure Boot enabled systems. That process will be defined between VotingWorks and SLI in more detail, but an initial overview of options can be found in .
Open virt-manager (if not already open):
Double-click the offline VM
Press the Start button ▶️
Once the VM has initialized, log in with username: vx and password: votingworks
To ensure the console displays correctly, select the “View” menu option, then “Resize to VM”
In a terminal window, validate that in the offline VM through the following command:
This command should either time out or immediately error with a failure in name resolution.
Ensure the USB drive created in the online phase is attached to the build machine.
Make the USB available to the offline VM:
From the menu, select Virtual Machine
In the dropdown, select Redirect USB Device
In the dialog box that opens, select the USB drive you attached, then close the dialog
The USB drive will usually be available as /dev/sda1. To confirm, you can use:
If it’s accessible by a different path, that’s fine, just make a note of it and use that path in the following steps as appropriate.
Once the offline phase completes, the base VotingWorks application has been built. You can now shut down the offline VM via:
Once the offline phase completes, the base VotingWorks application has been built. You can now shut down the offline VM via:
This section maps to Requirement 14.2-K
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.
To install Debian 12 on the build machine (VxBuild), you will need to download the latest Debian 12 amd64 installer file here:
You should use a blank USB for this install drive. The process described below will wipe any existing content.
To create a USB install drive with the downloaded iso file:
Ensure the USB 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:
If the USB is not attached as the /dev/sda device, that’s ok. Simply replace “/dev/sda” with the device your USB did attach to.
NOTE: The command below should not include any number as part of the device path. As an example, if the above command returns “/dev/sda1”, you must use “/dev/sda” as the path in the next command.
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.2. Please update to the appropriate filename if you use a newer version.)
Once the above command completes, you can safely remove the USB install drive from your system.
Before turning the VxBuild system on, insert the USB install drive created in the previous step.
Boot the system from the USB install drive. (After powering the build machine on, begin pressing F12 until it enters the Boot Menu)
You will be presented with the following screen:
Select Graphical Install and press Enter
Select your preferred language and click Continue.
Select your location and click Continue.
Select your keyboard layout and click Continue.
Select your network device (may differ from screenshot) and click Continue.
If using a wireless connection, follow the next steps. If using a wired connection, it will configure automatically.
Select your network device (may differ from screenshot) and click Continue.
Select WPA/WPA2 PSK and click Continue.
Enter your wireless network password and click Continue.
Enter “VxBuild” for the hostname and click Continue.
Leave the domain name blank and click Continue.
Set the root user password and click Continue.
Enter “Vx” for the full name for the new user and click Continue.
Enter “vx” as the username and click Continue.
Enter a password for the “vx” user and click Continue.
Select your timezone and click Continue.
Select “Guided - use entire disk” and click Continue.
Select the “/dev/nvme0n1” disk and click Continue.
Select “All files in one partition” and click Continue.
Select “Finish partitioning and write changes to disk” and click Continue.
Select “Yes” and click Continue.
The base OS installation will now begin. During the installation you will be asked to answer questions related to package management.
Select “United States” and click Continue.
Select “deb.debian.org” and click Continue.
Leave the proxy information blank and click Continue.
The installation process will continue automatically. You will be asked to configure “popularity-contest”.
Select “No” and click Continue.
Select the options as shown above and click Continue.
The installation process will continue. Once it completes, you will be presented with a final screen confirming it was successful.
Remove the USB drive and Click Continue.
The system will reboot and automatically start Debian 12
Log in with the “vx” user and password you created during the installation process.
Several basic configuration prompts will be displayed.
Select Next.
Select your keyboard preference and click Next.
Turn off Location Services and click Next.
Do not configure any Online Accounts. Select Skip.
Click the “Start Using Debian GNU/Linux” button. The dialog will be closed.
The “vx” user needs to be granted sudo privileges related to configuring and initializing the build environment tools. To do this, open a terminal window. (TODO: terminal instructions)
The “vx” user needs to be granted sudo privileges related to configuring and initializing the build environment tools. To do this, open a terminal window. (TODO: terminal instructions)
As the “vx” user, you will temporarily log in to the “root” account.
You will see your terminal window prompt change to “root@VxBuild”. To grant the “vx” user sudo privileges, run the following command as root.
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:
The command should return “root”. This confirms sudo privileges have been granted correctly.
While you can perform this final phase in the offline VM created in the previous step, we recommend cloning the offline VM for each specific VotingWorks application to save time. By cloning the offline VM, you only need to perform the application specific configuration since they share the same base application code.
In the following steps, the vxadmin VM will be referenced. In future tests or builds, these steps can be repeated for each different VotingWorks application: vxcentralscan, vxscan, and vxmark.
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.
Open virt-manager (if not already open):
Double-click the vxadmin VM
Press the Start button ▶️
Once the VM has initialized, log in with username: vx and password: votingworks
To ensure the console displays correctly, select the “View” menu option, then “Resize to VM”
In the vxadmin VM terminal:
You will be guided through several questions.
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.
This section walks through all steps to install a trusted build image on a VotingWorks component using through the following major steps:
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 , many of which are used for production configuration
— The applet that we’re installing onto our Java Cards
Lenovo uses a TPM 2.0 chip by Nuvoton, the NTC 75x series, covered by the same CMVP for FIPS compliance:
We use OpenSSL v3 with the hardware module, which outsources all cryptographic operations performed with secret keys to the underlying TPM 2.0 chip, which, as specified above, are FIPS compliant. See for calling OpenSSL with the appropriate hardware module.
For verification of signatures, we use OpenSSL in software mode. This does have a CMVP:
On the other hand, VxSuite strongly authenticates all data, which is critical. Thus, CVRs and election definitions are in plaintext on the USB drives that transfer them, accompanied by strong digital signatures, rooted in signing keys stored in hardware TPMs, as described in .
You will now need to perform the process with VotingWorks. Once that process is completed, the VM is signed for use with Secure Boot.
At this point, you are ready to install the image. You can find those instructions in .
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 importnat.
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.
Open virtmanager:
Double-click the online VM
Press the Start button ▶️
Once the VM has initialized, log in with username: vx and password: votingworks
To ensure the console displays correctly, select the “View” menu option, then “Resize to VM”
In the terminal window, run the following commands:
You will be prompted for sudo password.
The online phase will take awhile to complete. Once it finishes, you need to attach a USB drive to the build machine. This USB drive will be used to transfer all necessary tools and code to the offline VM. To make the USB available to the online VM:
From the menu, select Virtual Machine. In the dropdown, select Redirect USB Device. In the dialog box that opens, select the USB drive you attached, then close the dialog.
In the online VM terminal:
You will be prompted to select the USB drive. Once selected, all necessary code repositories and build tools will be exported to the USB. After the export is complete, you can shut down the online VM:
Be sure you’ve removed any attached USB devices. After you’ve imaged a machine, the machine will boot into a configuration wizard. The majority of steps are self-explanatory, but "Step 1: Set Machine ID" and “Step 4: Create Machine Cert” require some extra clarification.
Set Machine ID
This step defines the machine ID for a system. This will be referenced by the VotingWorks application along with system logs. It is important the machine ID be unique for each system. For example, if you are configuring two VxScan systems, you could use SLI-SCAN-01 and SLI-SCAN-02.
When configuring a VxAdmin, you’ll be prompted to:
Enter a jurisdiction ({state-2-letter-abbreviation}.{county-or-town}, e.g. ms.warren or ca.los-angeles):
You can use “us.sli” as your jurisdiction.
For this step, please use the USB drive labeled VxCertifier.
When configuring any machine, you’ll be told to insert a USB, to which a certificate signing request will be written. After the certificate signing request is written, you’ll be prompted to:
Remove the USB, take it to VxCertifier, and bring it back to this machine when prompted. Press enter once you've re-inserted the USB.
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 to VxCertifier, our VotingWorks certification terminal. We’ll need to use a remote certification process instead.
You’ll need to remove the USB, find the “csr.pem” file inside the “certs/” directory on the USB, 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 USB that you started with, placing it in the same USB’s “certs/” directory. Re-inserting this USB into the machine and pressing enter should allow you to proceed successfully.
Once you have certified the machine, you will need to program a system administrator smartcard. You should remove any connected USB devices and connect the card reader provided by VotingWorks. (For Lenovo laptops, you can use the built-in card reader on the bottom left side of the machine.) Follow the prompt and be sure to record the PIN. After rebooting, you can log in with the smartcard and PIN.
As a final verification for this build, you should log in with the System Administrator smartcard and load an election definition.
After completing that, you should program an Election Manager smartcard: Programming Smart Cards
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 VMs 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 repository, in playbooks/virtmanager/clone-base-vm.yaml.
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.
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.
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.
Debian’s package manager, apt, is built on a secure framework described here: SecureApt
The VotingWorks build process relies on this fundamental tool to install many of the system level tooling 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.
Python’s package manager, pip, does not verify package integrity by default. However, secure installation is possible via the method described here: Secure pip installs
The VotingWorks build process implements the above method in the tb-install-ansible.sh 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: Debian 12 x86 pip requirements
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: FPM 1.15.1
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: rubygems.yaml
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: rust.yaml
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: Cargo Manifest and Cargo Lock
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: node.yaml
Npm is the default Node package manager. It is installed as part of the Node install previously described.
Packages installed via npm are checked against the officially provided checksums for each package. You can see that checksum verification in the node playbook here: node.yaml
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 only the explicit packages required are installed.
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 only the explicit packages required are installed.
To install a VotingWorks application on hardware, we have created a simple install tool: vx-iso.
There are two USB drives involved in the installation process:
Vx-iso - an Arch Linux iso installer program. This USB has been provided to you.
Vx-data - An empty USB drive to which you will copy a previously created VotingWorks application image. This USB is also provided.
To create a functional Vx-data USB drive, on the host build machine, you need to attach the USB you will be using. Be aware, any existing contents of the USB will be erased. You will also need to know the full path to the VotingWorks application image you want to install. Using the vxadmin image referenced in the Trusted Build process, the path to that image will be:
Once you know the full path to the image file, run the following steps as the previously created “vx” user:
You will be prompted to select the USB device by typing the device name, e.g. “sda". Once selected, the image will be automatically copied to the USB. It can safely be removed once the process completes. Proceed to "Installing a VotingWorks Image" instructions.
Operating System: Debian 12
Minimum 8GB RAM
X86_64 / AMD64 CPU architecture Intel i5 or higher
Minimum 250 GB storage
Debian 12 will need to be installed on the build machine. You can find detailed instructions for that process in the Installing Debian 12 to VxBuild section. Once that is complete, follow these steps to install the VotingWorks build system: vxsuite-build-system.
Throughout the rest of this document, substitute <inventory name> w/ the inventory provided by VotingWorks.
At this point, you should have three separate VMs: debian12base110-frozen<date>, online, and offline. You can confirm this by running:
The debian12base110-frozen<date> VM will not be used unless you need to clone the online or offline VMs at a later time.
This section maps to Requirement 1.2-B
Marks are determined valid and counted by the system if the amount of darker pixels in the bubble area exceeds a configurable threshold. This threshold can be adjusted to have a stricter or looser interpretation of what is considered a valid mark. The recommended and default threshold in the system is 7%, under which 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.
To finalize an image for production use, it is necessary to implement Secure Boot. 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.
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 will be 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 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 verified and the VM has been successfully defined, normal Secure Boot processes can be followed, while SLI observes.
Once the Secure Boot configuration has been completed, VotingWorks will retrieve the image signature from the admin menu. This hash will be provided to SLI/EAC for official verification of the image.
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 secure build machine:
Once this step has completed, SLI can download the files at their convenience. On the SLI build machine:
Once SLI has completed the download and hashes are validated, the compressed image and signature can be provided to EAC for use by election officials. At any point after submission to EAC, election officials can verify the image hash via the vx-iso tool.