commit | 35d397cd451a2b7c55e6a7a42e4d6327addf3487 | [log] [tgz] |
---|---|---|
author | Todd Wang <toddw@google.com> | Mon May 23 14:33:39 2016 -0700 |
committer | Todd Wang <toddw@google.com> | Mon May 23 14:33:39 2016 -0700 |
tree | c5562ae8d672bdd4218cc4c29faa91ffcf488a12 | |
parent | 406a5839b93ae009d126db1f9474cf749d146370 [diff] |
Speedup and cleanup vom encoder, some bugfixes. This brings the vom Encoder implementation into a reasonable state, performance-wise. The technique is the same as on the decoder side: https://vanadium-review.googlesource.com/#/q/topic:toddw-fastdec Also fixed a bug in the handling of bytes in vdl.newPipe. Added a bunch of comments in v.io/v23/vdl/pipe.go to describe the general mechanism. The important files to look at are under: v.io/v23/vdl v.io/v23/vom v.io/v23/verror v.io/x/ref/lib/vdl/codegen/golang Here are the encoding benchmarks. Note that there is higher variance for these numbers than the decoder numbers, since encoding requires allocations on the output buffer. Our solution to that will be chunked encoding, which isn't implemented here. benchmark old ns/op new ns/op delta Vom___Encode_____XNumber 6647 4216 -36.57% Vom___EncodeMany_XNumber 472 428 -9.32% Vom___Encode_____VNumber 6482 5542 -14.50% Vom___EncodeMany_VNumber 176 174 -1.14% Vom___Encode_____XStringSmall 6862 6531 -4.82% Vom___EncodeMany_XStringSmall 527 460 -12.71% Vom___Encode_____VStringSmall 6257 5685 -9.14% Vom___EncodeMany_VStringSmall 196 188 -4.08% Vom___Encode_____XStringLarge 133510 120660 -9.62% Vom___EncodeMany_XStringLarge 55130 52237 -5.25% Vom___Encode_____VStringLarge 130751 129680 -0.82% Vom___EncodeMany_VStringLarge 53851 51242 -4.84% Vom___Encode_____VEnum 7093 6172 -12.98% Vom___EncodeMany_VEnum 191 183 -4.19% Vom___Encode_____XByteListSmall 7351 6873 -6.50% Vom___EncodeMany_XByteListSmall 579 472 -18.48% Vom___Encode_____VByteListSmall 6623 6157 -7.04% Vom___EncodeMany_VByteListSmall 187 177 -5.35% Vom___Encode_____XByteListLarge 104355 104017 -0.32% Vom___EncodeMany_XByteListLarge 8676 8696 +0.23% Vom___Encode_____VByteListLarge 97597 100401 +2.87% Vom___EncodeMany_VByteListLarge 8052 8231 +2.22% Vom___Encode_____XByteArray 7364 7530 +2.25% Vom___EncodeMany_XByteArray 745 749 +0.54% Vom___Encode_____VByteArray 6595 6139 -6.91% Vom___EncodeMany_VByteArray 215 202 -6.05% Vom___Encode_____XArray 8624 7307 -15.27% Vom___EncodeMany_XArray 1266 630 -50.24% Vom___Encode_____VArray 7358 6523 -11.35% Vom___EncodeMany_VArray 370 274 -25.95% Vom___Encode_____XListSmall 8184 6991 -14.58% Vom___EncodeMany_XListSmall 1505 688 -54.29% Vom___Encode_____VListSmall 7000 6308 -9.89% Vom___EncodeMany_VListSmall 390 288 -26.15% Vom___Encode_____XListLarge 21629416 4103590 -81.03% Vom___EncodeMany_XListLarge 20971508 3440893 -83.59% Vom___Encode_____VListLarge 4816700 2821262 -41.43% Vom___EncodeMany_VListLarge 4226822 2257347 -46.59% Vom___Encode_____XListAnySmall 20538 20456 -0.40% Vom___EncodeMany_XListAnySmall 11473 10555 -8.00% Vom___Encode_____VListAnySmall 17542 13722 -21.78% Vom___EncodeMany_VListAnySmall 9502 5963 -37.24% Vom___Encode_____XListAnyLarge 242633472 186445853 -23.16% Vom___EncodeMany_XListAnyLarge 231676344 184135888 -20.52% Vom___Encode_____VListAnyLarge 243393646 232625450 -4.42% Vom___EncodeMany_VListAnyLarge 204297618 208020229 +1.82% Vom___Encode_____VSet 7379 6520 -11.64% Vom___EncodeMany_VSet 539 435 -19.29% Vom___Encode_____XMap 10599 9060 -14.52% Vom___EncodeMany_XMap 3338 2743 -17.83% Vom___Encode_____VMap 6516 7004 +7.49% Vom___EncodeMany_VMap 719 527 -26.70% Vom___Encode_____XSmallStruct 11613 10277 -11.50% Vom___EncodeMany_XSmallStruct 2094 1630 -22.16% Vom___Encode_____VSmallStruct 9404 8227 -12.52% Vom___EncodeMany_VSmallStruct 470 405 -13.83% Vom___Encode_____XLargeStruct 63816 51583 -19.17% Vom___EncodeMany_XLargeStruct 37361 28332 -24.17% Vom___Encode_____VLargeStruct 37287 32095 -13.92% Vom___EncodeMany_VLargeStruct 11101 9271 -16.49% Vom___Encode_____XLargeStructZero 43606 40770 -6.50% Vom___EncodeMany_XLargeStructZero 19131 17869 -6.60% Vom___Encode_____VLargeStructZero 23724 23690 -0.14% Vom___EncodeMany_VLargeStructZero 224 217 -3.12% Vom___Encode_____VSmallUnion 9225 7531 -18.36% Vom___EncodeMany_VSmallUnion 266 227 -14.66% Vom___Encode_____Time 9340 10026 +7.34% Vom___EncodeMany_Time 1794 1732 -3.46% Vom___Encode_____Blessings 41833 38908 -6.99% Vom___EncodeMany_Blessings 5743 5291 -7.87% Vom___Encode_____RPCRequestZero 50452 47035 -6.77% Vom___EncodeMany_RPCRequestZero 217 208 -4.15% Vom___Encode_____RPCRequestFull 63186 56772 -10.15% Vom___EncodeMany_RPCRequestFull 5448 4803 -11.84% Vom___Encode_____RPCResponseZero 51641 45973 -10.98% Vom___EncodeMany_RPCResponseZero 809 831 +2.72% Vom___Encode_____RPCResponseFull 101767 105144 +3.32% Vom___EncodeMany_RPCResponseFull 57135 55317 -3.18% MultiPart: 4/5 Change-Id: I60849a228d09b891854cd50fa96eb8b54b8198a2
This project defines the software for building a secure physical lock using the Vanadium stack, along with a commmand-line tool for interacting with the lock. The software runs on a Raspberry Pi and interacts with the locks's switches and sensors using GPIO. It runs a Vanadium RPC service that allows clients to send lock and unlock requests.
Before describing the design in detail we highlight its key distinguishing aspects:
Decentralized: There is no single authority on all the locks, no cloud server that controls access to all locks from a particular manufacturer. All secrets and credentials pertaining to a particular lock are solely held by the lock and its clients. Huge compute farms run by hackers all over the world have no single point of attack that can compromise the security of multiple locks.
No Internet Connectivity Required: The lock does not require internet connectivity to function. When you’re right in front of the device, you can communicate with it directly without going through the cloud or a third-party service.
Audited: The lock can keep track of who opened the door, when and how they got access.
An out-of-box lock device exposes the UnclaimedLock
interface on startup.
type UnclaimedLock interface { Claim(name string) (security.WireBlessings | error) }
This interface has a single method Claim
that can be used to claim the device with a specific name and obtain credentials that grant authorization for subsequently interacting with the lock. Once claimed, the device exposes the Lock
interface.
type Lock interface { // Lock locks the lock. Lock() error // Unlock unlocks the lock. Unlock() error // Status returns the current status (locked or unlocked) of the // lock. Status() (LockStatus | error) }
Clients that possess the appropriate authorization credentials can interact with the device and send it requests to lock, unlock or determine the status.
An out-of-box lock device comes with pre-installed credentials (private key and blessings) from its manufacturer. For instance, it may have blessings of the form <lock manufacturer>:<serial no>
. The UnclaimedLock
interface exposed by it is accessible to everyone.
When the lock is claimed with a specific name, it blesses itseld under the name and uses that blessing to subsequently authenticate to clients. It also creates a blessing for the claimer by extending this (self) blessing with the extension key
. For e.g., a lock claimed with the name front-door
will subsequently authenticate with the blessing front-door
, and grant the blessing front-door:key
to the claimer.
The blessing granted to the claimer is the key to the lock. It provides access to the methods on the Lock
interface exposed by a claimed lock device. Furthermore, all extensions of this key blessing are also authorized to access the Lock
interface.
Access to the lock can be shared with other principals by blessing them with the key blessing. Appropriate caveats may be added to this blessing to limit the scope of use. For e.g., the key front-door:key
can be shared with a house guest for a limited period by extending it as front-door:key:houseguest
with an expiration caveat.
Both claimed and unclaimed lock devices advertise their endpoints using MDNS to allow clients to discover them without going through the cloud or a third-party Mounttable. All lock devices advertise themselves with names that are prefixed with lock-
. This prefix allows clients to easily filter MDNS advertisements for lock devices.
An unclaimed lock device advertises under a name of the form lock-unclaimed-lock-xxxxxx
where xxxxxx
is a random number generated by the lock device. A claimed lock device advertises itself under the name lock-<claimed name>
.
Currently we don't have any protection for preventing a rogue device from impersonating the MDNS name of a lock device. This is something we plan to add in the future. Note that impersonating the MDNS name of a lock device may lead to denial of service but does not compromise the security of the lock.
The Lock
interface has methods to lock, unlock and determine the status of the lock device. The device logs the blessings of the caller for all method requests thereby maintaining an audit trail. Internally, these methods set or unset certain GPIO pins on the Raspberry Pi based on the circuitory described below.
Apologies for this unconventional, possibly unreadable circuit representation. Putting it down so that the author can remember! TODO(ashankar): Clean it up!
The pin number assignments here work both for RaspberryPi Model B/B+ and RaspberryPi2-ModelB.
---(Pin 1)-------/\/\(10KΩ)/\/\---------(COM port of magnetic switch) \ \----/\/\(1KΩ)/\/\---------(Pin 15 = GPIO22) \ \----(LED)-----| | | (N.O. port of magnetic switch)--| | | (-ve terminal of active buzzer)--| | | | (Pin 6 = GND)--| ---(Pin 11 = GPIO17)-----------(+ terminal of active buzzer)
The above ciruit is meant to be a simulation of an actual lock device wherein locking and unlocking simply makes a buzzer ring. In particular the Lock
and Unlock
calls update the status of the pin GPIO17
, and the Status
call checks the status of the ping GPIO22
.
Building the lock service for the RaspberryPi
jiri go get -u github.com/davecheney/gpio JIRI_PROFILE=arm jiri go install v.io/x/lock/lockd scp $JIRI_ROOT/release/projects/physical-lock/go/bin/lockd <rpi_scp_location>
If building without the arm
profile, there are no physical switches/relays and instead a simulated hardware is used that uses the interrupt signal (SIGINT) to simulate locking/unlocking externally.
The lock service can be started by running the following command in the directory where the lockd
binary was copied.
lockd --v23.credentials=<creds dir> --config-dir=<config dir>
The --config-dir
flag specifies a path to a directory where configuration files can be saved, and the --v23.credentials
flag specifies a path to the Vanadium credentials directory for lockd
. The configuration directory must be persisted accross restarts; emptying it would amount to a “factory reset”.
We describe a few commands for discovering and interacting with a lock device.
The first step is to build the command-line tool.
jiri go install v.io/x/lock/lock
In the rest of this section, we specify all commands relative to the directory containing the lock
tool.
All commands must be run under an agent that has a blessing from dev.v.io
. This can be achieved by starting bash
under an agent and using the principal
tool to obtain a blessing from dev.v.io
.
jiri go install v.io/x/ref/cmd/principal jiri go install v.io/x/ref/services/agent/... $JIRI_ROOT/release/go/bin/agent --v23.credentials=<creds> bash $JIRI_ROOT/release/go/bin/principal seekblessings
Above, <creds>
points to a directory where the tool's Vanadium credentials would be persisted.
Find the names of nearby lock devices (on the same network as this tool)
lock scan
This command prints out the names of nearby lock devices. The name of an unclaimed lock device always begins with unclaimed-
, and the name of a claimed lock device is the name under which it was claimed.
The claim
command can be used to claim an unclaimed device. For instance, the following command claims the device unclaimed-lock-xxxxxx
with the name front-door
. (Here unclaimed-lock-xxxxxx
is the name of the unclaimed lock device obtained from the scan
command.)
lock claim unclaimed-lock-xxxxxx front-door
The lock would now authenticate with the name front-door
and a subsequent invocation of scan
should print the name front-door
.
The listkeys
command lists the set of available physical-lock keys and the names of the locks to which they apply.
lock listkeys
For example, as a result of the previous claim, the key front-door:key
would show up as being available to this tool for the lock front-door
.
The lock front-door
can be locked using
lock lock front-door
and unlocked using
lock unlock front-door
The status
command can be used to determine the current status of the lock.
lock status front-door
The lock
tool can also be used to share keys with nearby users (on the same network as this tool). This involves the following steps.
First, the receiver must run the recvkeys
command on their lock
tool.
// At the receiver lock recvkeys
As a result of this command, the receiver's lock
tool would start a server for receiving keys and advertise the endpoint of the server over MDNS.
Next, the sender must then search its neighborhood for users waiting to receiving keys
// At the sender lock users
This command would print the email addresses of all users waiting to receive keys. Once the email address of the receiver is visible then this command can be stopped and sendkey
command can be used to send a key.
For instance, the following command sends the key for lock front-door
to the user john.smith@gmail.com
that is only valid for 10 minutes.
// At the sender lock sendkey --for=10m front-door john.smith@gmail.com friend
Above, friend
is the category used to classify the receiver.
The sendkey
command would cause the receiver to see a prompt specifying the name of the key received and the blessings of the sender. Once the receiver confirms saving the key, he/she would be able to use it to interact with the lock front-door
for next 10 minutes. Executing the listkeys
command would reveal the key front-door:key:friend
along with its expiration time.
AuditLog(startTime, endTime time.Time) []AuditLog | error type AuditLog struct { Blessing string Action LockStatus Timestamp time.Time }
We'd also have to work out how to control access to this AuditLog
. One option is to use caveats - so when “making” a new key one can choose to insert the “noadmin” caveat?
sendkey
command only supports expiration commands. In the future, we would like to support at least the following caveats: