Turn in homework
The voter casts his vote on a voting machine. Before allowing him to vote, the machine insists that he insert the voter card. The machine interacts with the voter card, and if it likes the interaction, it disables the voter card and allows the voter to cast a vote.
After the voter is done voting, the machine ejects the now-disabled voter card, and the voter gives the voter card back to the election workers at the front desk before leaving the polling place. (The voter card may later be re-enabled for use by another voter.)
The idea of this scheme is that an enabled voter card allows one vote to be cast. Unfortunately, Diebold's implementation of this scheme is insecure, allowing an adversary to re-enable his own voter card as often as he likes, and thereby to cast as many votes as he likes. Your job is to fix this.
The voting machine is a computer. It plugs into the wall and looks like an oversized laptop. It has a slot into which a voter card can be inserted. When a voter card has been inserted, the voting machine interacts with the card and then decides whether to allow a vote to be cast. If necessary, it interacts with the voter card to tell the voter card to disable itself.
The voter card is a smartcard -- a little computing device the size and thickness of a credit card that has a processor and some persistent memory. The voter card doesn't have its own power source; when it is inserted into another device (e.g. an encoder or voting machine) it gets power from that device and is able to run code. But when it is removed from the other device it stops running and loses its program counter, registers, and so on. The persistent memory is the only part of the card's state that is preserved when it is removed from its power source.
When the voter card is inserted into another device, the voter card can communicate with that device using a bidirectional serial channel. For example, the voter card can send a byte to the other device, and the other device can receive that byte; or vice versa. This is the only way the devices can interact.
It is important to recognize that the voter card is a computer in its own right. Other devices, such as the encoder and voting machine, can never read or write the voter card's memory directly. All they can do is communicate with the voter card and rely on it to change its state.
The createCard program creates a new smartcard. Its job is to initialize the persistent memory of the new smartcard. When you invoke createCard, you give it a filename; createCard creates a new file with that name, and stores the smartcard's persistent memory in that file. You can have as many smartcards as you want -- there will be one file for each card, to hold the contents of that card's persistent memory.
The encoder program is invoked whenever an election worker pushes the "enable voter card" button on the encoder device. encoder takes one commandline argument, which is the name of a file containing (the persistent memory) of a smartcard; this smartcard is assumed to be inserted into the encoder device when the button is pressed.
The encoder program does some initial setup steps in its main function, which you are not allowed to change. One of these steps is to launch a separate program that represents the inserted smartcard. These two programs run simultaneously, communicating via a serial connection, just as the real encoder would communicate with a real smartcard that is inserted into it.
Having set everything up correctly, encoder's main function then calls the activateEncoder function, which does the main work of the encoder. This is what you will change.
The voting machine program, called machine, works similarly to the encoder. It takes one commandline argument (the name of a file containing a smartcard's persistent memory). It does some setup, which includes launching a program to represent the smartcard. Then it calls a function called activateMachine, which does the main work of the voting machine and which you can modify.
The final program is the smartcard program, which is invoked whenever a smartcard is inserted into a device. This program does some initial setup steps, which we have provided and you may not modify. Then it calls the activateCard procedure, which you may modify. This procedure is invoked whenever the smartcard is inserted into another device. Read the comments in activateCard.c for more information.
Normally, you will not launch smartcard directly. Instead, it will be launched automatically when you run encoder or machine.
We have provided working (but insecure) code for all of these programs (and for another program, dumpCard which you may find useful but you are not required to use). It's probably a good idea to read the code for these programs, and to run them after adding "hello world" code to the activate* procedures, to get a better handle on how the pieces fit together.
The encoder and machine programs we have given you do not use any persistent storage. You can give them persistent storage if you want. If you do this, the persistent storage should be kept in a file, and of course one program's persistent storage should never by accessed by another program.
Even if the adversary makes his own smartcards and inserts them into your encoder and/or your voting machine, he should never be able to cast a vote without having used the encoder to enable a card first.
Your solution should be a zip-file containing your source code (including any provided files that you did not modify), a Makefile, and a report that describes what you did and why. The report should be an HTML file named index.html. (It may contain links to other files, if you include those files in your submission.)
When we unzip your submission into a directory and type "Make" there, it should build programs that we can execute by typing "createCard", "encoder", "machine", and "smartcard", which operate as described above.
You must work in a group on this assignment. You may not collaborate with anyone outside your group.