Access Protocol

From Hive13 Wiki
Jump to navigation Jump to search

Overview

Catalyst App

  • GitHub link
  • Add in OpenID Support
    • Facebook/Foursquare Checkins to the hive on entry
    • Twitter updates on entry
  • IRC Notifications

Hardware

Future

  • Screen to display information
  • Current measurement to measure how long a tool is on.
  • Log general stuff

current use cases

  • Doors
  • Tools
    • How to end use
      • Timeout
      • Current monitoring
      • "Finish" button
      • Least controversial method so far is tap card to enable tool, push a button to disable tool when finished. No timeout.
  • Vending machines
    • Need to deduct credits/dollars from a stored value securely.
  • Member registration/payment terminal
    • Need to securely add credits/dollars to a stored value.
    • Need to also be able to associate a card ID with an account. Maybe multiple card/phone IDs? PIN as well

Protocol and Database Info

Server <-> RFID reader protocol

  • Each request is sent from the RFID to the server as a POST with a JSON body.
  • Each device has a key pre-shared with the server to mutually authenticate w/o SSL, which some of our MCUs have no hope of doing.
  • The body object contains a device key with the name of the device requesting access - if the server doesn't know about this device, it'll fail.
  • The body object contains a data object with the body of the request. It can have several fields in it.
    • version - integer - 1 is assumed if not specified. Version of the API to use.
    • operation - string - access is assumed if not specified. Other options are vend and log.
    • badge - integer - for vend or access. Contains the presented badge number.
    • random - array of integers - this is random per-packet data to stop replay attacks
    • random_response - array of integers - this must be copied from the request to the response if present; this solves a different subset of replay attacks.
  • The checksum is computed like this: (Here's where it's done on the server.)
    1. Sort all of the keys recursively on the data object.
    2. Remove all unnecessary whitespace.
    3. Prepend the device's shared key.
    4. Take the SHA-512 checksum of that string - encode as a hex string - it's case-insensitive everywhere, but I use uppercase.
    5. Create an object with keys of data, device, and checksum - that object is the body of the request or response.

Changes in Version 2

  • Version 2 of the API stops replay attacks from the client to the server. The server has a 16-byte nonce it expects the client to send with the packet or else it'll fail.
  • A get_nonce operation has been added to the operations. It'll silently succeed on version 1 packets, but will return the expected nonce for the next packet otherwise.
  • The nonce must be submitted in the data object as nonce.
  • Instead of a response Boolean and an error text to indicate error condition, there are several Booleans added for each part of the verification process.
    • The order in which they are generated - and in which they should be checked - is checksum_valid, version_valid, nonce_valid, and operation_valid. Subsequent fields may not be present in a response if a field is set to false. The error and response fields are now used by the individual operations to indicate success and provide operation-specific errors.

General-purpose logging

  • JSON body with data, device, and checksum as described above - TBD what to do about an unknown device.
  • Data field has key option set to log
  • An optional key is current_timestamp in milliseconds, to batch several logs and let the server figure out the timesamps - millis() in Arduino-land works here.
  • Key messages is an array of message objects, containing keys as below:
    • absolute_timestamp has the server compare it to current_timestamp to figure out when the message was generated. Optional.
    • relative_timestamp is how long ago (this number is only positive) the message was generated. Optional.
    • If neither are specified, the server will timestamp the message with when it hit the DB. If both are specified, prepare for nasal demons.
    • data is the message text. No reasonable length limit. Required; the array member will be silently discarded without it.
    • severity is the 0-7 standard syslog values (panic, alert, crit, error, warn, notice, info, debug). Optional; defaults to info.
  • Key temperatures is an array of temperature reading objects to log, containing keys as below:
    • absolute_timestamp and relative_timestamp function as in messages. Missing means use the timestamp for the packet as a whole.
    • temperature is the reading, in tenths of a degree Fahrenheit. This is done to remove the need for floating-point libraries on microcontrollers, as they are large. Required.
    • item is which item the temperature is measuring. Note that a device must have permission to that item to log temperatures for it. Required; the array member will be silently discarded if missing or unauthorized.

Current protocol weaknesses and notes

  • You can capture a Version 1 packet going to the server and replay it again and again and the server will accept it and process it.
    • This could add junk log entries to the access log.
    • This could also drain someone's soda credits.
    • This has been fixed in the version 2 API. There are also two fields in the DB stating the minimum and maximum version each device can use.
  • You CANNOT replay the response to a successful badge swipe and open the door, because
    1. The MCU only listens after a badge is presented (or a temperature is logged, but it won't call door_open() from that function).
    2. The MCU generates a new "random_response" field
    3. The MCU verifies that the response packet's field matches what it sent.

Database Layout

  • Conventions
    • All tables have a ${table_name}_id column that's a UUID as the primary key
    • Many-to-many tables have the two tables they connect in alpha order
      • They do not have their own, separate ID field
      • They have the primary key as the two tables in alpha order
      • There is a second key of the two columns reversed (this way is needed for the other foreign key)
    • Table names are singular
    • Catalyst convention is to use Pascal case for table names.
    • Postgres convention is to use Snake case for table names.
    • Use TIMESTMAP WITH TIME ZONE for all timestamp columns.
  • members stores member information.
    • It needs renamed to member for consistency, though the app calls it Member with a name override.
    • It also needs old fields blown away.
  • badge stores a badge number and which member it belongs to - you can have multiple badges per account
  • mgroup stores the names and IDs of various groups, such as members, leadership, laser certified, &c. It's called mgroup because group is an SQL reserved word.
  • member_mgroup is a many-to-many association table to join members to groups.
  • device stores information about a device - its shared key and name right now.
  • item stores information about items that can be accessed - doors, tools, and so on.
  • device_item is a many-to-many showing which devices can service which items.
  • item_mgroup is a many-to-many granting access to an item to a group.