Table of Contents
New America Foundation - Contractor Agreement #32-OTIUSAID2013 “NAF5”
In September 2013, The Serval Project commenced a fifth round of work for the New America Foundation's Open Technology Institute to improve Serval DNA key management to allow Commotion OpenBTS to assign a Serval Identity (SID) to each GSM handset and migrate the identity from node to node to follow the GSM handset. This involves adding multi-key support for node addressing, allowing each node to announce multiple keys, and enabling multiple identities for each node.
Section 1: Work to be Performed (Scope of Work)
- R2. Implement
servald id enter pin <PIN>
which unlocks any SID identities protected by that PIN. If the SID already has a remote route, then the SID is not announced, but if no remote route exists, then the SID is announced as routable to this node. Returns the list of identities unlocked by that pin, and whether each is announced or already has a remote route.
Technical notes
The following implementation decisions were made during the course of the contract.
- N1. The R2 and R4 keyring PIN enter and relinquish commands only affect entry PINS not keyring PINs. A running daemon can have at most one keyring PIN, which is set by the command-line option when started and cannot be relinquished while running.
- the keyring.c code supports many “contexts”, each one with its own keyring PIN;
- the first “context” is always created, and is for the null (empty) keyring PIN,
- the commandline.c command-line API only supports a single
--keyring-pin=PIN
option, which creates a second “context” if used - the commandline.c command-line API already supports many
--entry-pin=PIN
options, however these should not be used for identities that are intended to be dynamically unlocked and locked (see N3)
- N2. The daemon uses one SID as its main identity for its entire lifetime. All other SIDs are treated as secondary identities.
- the daemon automatically unlocks all PIN-less identities it can find in the keyring on start-up, as well as any whose PINs are supplied on the command line
- if there are none, the daemon creates a PIN-less one automatically and stores it in the keyring (for re-use in future sessions)
- the daemon chooses the first unlocked, start-up SID as its main identity
- the daemon does not allow its main identity to be relinquished (locked)
- N3. The Serval DNA daemon opens its keyring and applies the command-line supplied PINs before starting its routing engine. This has the following consequences:
- a daemon cannot perform identity hand-over requests while starting up, in order to gain custody of its initial identities
- thus, if two daemons are started with the same initially-unlocked identities in their keyrings, there will be a routing conflict on those identities;
- N5. The existing keyring.c code has a few flaws that were not remedied by this contract:
- unlocked keyring entries are used as a positive cache to avoid redundant unlocks:
- when unlocking with an entry PIN, the code first checks whether there are already any unlocked entries with the same PIN, and if so, does not perform an unlock scan through the keyring file
- however, if a PIN unlocks no entries, then re-trying the same PIN repeats the unlock scan (ie, there is no negative caching of PIN attempts) – functionally this is of no consequence, its only impact is on CPU use and hence potentially on battery life
- the running Serval DNA daemon does not re-load keyring entries from the keyring file while running, which leads to “stale cache” types of problems:
- if another process modifies the keyring file (eg, runs a
servald keyring add
command), the running daemon will not be aware of the change until re-started - the long-term objective is to re-implement all keyring operations as requests to the daemon process, which will resolve all “stale cache” and race condition bugs in one go
- however, in the meantime, the current implementation has some functional limitations (“bugs”) of which developers must be aware
- N6. The
id relinquish sid
command introduces a new functional flaw into keyring operations that is revealed by the following sequence of operations:- one enter PIN command unlocks two more identities
- a relinquish SID command then locks one of these identities
- a subsequent enter PIN command will not re-unlock that identity, because the positive caching (see N5) will detect that there are still identities bearing that PIN
- hence, in order for enter PIN to work as expected, ALL identities already unlocked with that PIN must be relinquished first
- for this reason, if the relinquish SID command is ever used, then for safety every enter PIN command should be immediately preceded by a matching relinquish PIN command
PROGRESS REPORT
Development commenced in September 2013, prior to the date of contract, and finished in mid October 2013. This report was completed at the start of December 2013, when the contract was submitted for approval as complete.
Implementation
R1 – multi-SID routing (completed 9 October)
- commit 0c1c767 automatically claims the route to any identity with an existing route when all possible routes disappear
R2 – servald id enter pin <PIN>
(completed 8 October)
R3 – servald id announce <SID>
(completed 13 October)
- commit b8ec568 implements the announce command:
- if a route to that SID already exists, then sends a challenge/response request to the existing instance of this SID,
- on receiving the request, the daemon locks the SID and responds
- on receiving the response, the daemon proceeds to unlock the SID and announce it as routable locally
R4 – servald id relinquish pin <PIN|SID>
(completed 14 October)
- commit ef7351b either:
R5 – keyring entry tags (completed 12 November)
- commit 9680b24 adds commands to read, write, and search a new key type for storing name/value pairs (“tags”), subject to the limitations described in N5:
- the new
keyring set tag <SID> <tag> <value>
command sets the value of a given tag on a given identity (which must be unlocked by the supplied PIN options) - the
keyring set did
command and the newkeyring set tag
command both list all DIDs and tags of the affected identity (after applying the modification) - the
keyring dump
command now includes tags in its output - the
keyring list
command does NOT include tags in its output (for backward compatibility reasons)
R6 – servald id list [<tag>|<SID>]
(completed 12 November)
- commit 4e543f7 implements the new
id list
command:- lists identities currently unlocked in the running daemon
- optionally filters by tag name and value
- does not include tags or DIDs in its output
R7 – automated test cases (completed 12 November)
- commit ae7e120 added the tests/keyring
KeyringEntryPinServer
test case for R2 (twoid enter pin
commands) - commit ef7351b expanded the tests/keyring
KeyringEntryPinServer
and tests/routingmigrate_id
test cases for R4 (addedid revoke pin
commands) - commit 534b01b added the new tests/keyring
DidName
test case, to ensure safety prior to refactoring the existingkeyring set did
command to use the new tag code