Skip to content

Instantly share code, notes, and snippets.

@bradfitz
Created February 23, 2013 23:57
Show Gist options
  • Save bradfitz/5021919 to your computer and use it in GitHub Desktop.
Save bradfitz/5021919 to your computer and use it in GitHub Desktop.
#include "sha1.h"
#include <SoftwareSerial.h>
SoftwareSerial SerialRNXV(2, 3);
int irVal = 0;
int distOn = 0; // getting distance
const int ms = 1; // unit of milliseconds
bool authed = false;
const int irValPin = 0; // the analog input pin for the ir reader
const int togglePin = 4;
const int buttonPin = 7;
const int unconnectedPin = 8; // for reading a "random" number from
const int challengeLength = 20;
char challenge [challengeLength+1];
const int lineBufCap = 80;
char lineBuf[lineBufCap];
int lineBufLen = 0;
void setup() {
Serial.begin(9600);
randomSeed(analogRead(unconnectedPin));
// start software serial for communication with wifly
SerialRNXV.begin(9600);
// set output pin for toggling the circuit that toggles the door line
pinMode(togglePin, OUTPUT);
// set input for button
pinMode(buttonPin, INPUT);
}
int nloop = 0;
int lastButtonState = 0;
int timeButtonDown = 0; // capped at kMaxInt
const int kMaxInt = 32767;
const int kShortPress = 12000;
int inLongMode = 0; // if >0, don't open garage. decremented every time wrap.
void loop() {
nloop++;
if (nloop == 0) {
wifiPrint("TIME_WRAPPED\n");
if (inLongMode > 0) {
inLongMode--;
}
}
if ((nloop & 0xfff) == 0xfff) {
int dist = analogRead(irValPin);
char buf[50];
sprintf(buf, "DIST %d\n", dist);
wifiPrint(buf);
}
if (SerialRNXV.available() > 0){
//char buf[12];
//int inByte = SerialRNXV.read(); // Read next byte
//Serial.println(itoa(inByte, buf, 10));
readWifiByte();
}
int buttonNow = (digitalRead(buttonPin) == HIGH);
if (buttonNow != lastButtonState) {
lastButtonState = buttonNow;
if (buttonNow) {
timeButtonDown = 0;
} else {
char buf[19]; // len("BUTTON_DOWN ") + 5 (32k) + len("\n\0")
sprintf(buf, "BUTTON_DOWN %d\n", timeButtonDown);
wifiPrint(buf);
int isShortPress = timeButtonDown <= kShortPress;
if (isShortPress && !inLongMode) {
toggleDoor();
}
if (!isShortPress) {
inLongMode = 3; // don't open garage on short press for 3 time wraps.
}
}
}
if (buttonNow && timeButtonDown < kMaxInt) {
timeButtonDown++;
}
if (distOn) {
delay(50);
// print
}
}
void readWifiByte() {
int inByte = SerialRNXV.read();
if (inByte < 0) {
return;
}
lineBuf[lineBufLen] = inByte;
lineBufLen++;
if (lineBufLen >= lineBufCap) {
lineBufLen = 0; // fuck it, too long of a line.
}
if (inByte == '*') {
if (lineBufHasSuffix("*OPEN*")) {
lineBufLen = 0;
generateChallenge();
SerialRNXV.print("\nCHAL ");
SerialRNXV.println(challenge);
} else if (lineBufHasSuffix("*CLOS*")) {
lineBufLen = 0;
}
}
if (inByte == '\n') {
lineBuf[lineBufLen-1] = '\0';
processWifiLine(lineBuf);
lineBufLen = 0;
}
}
void processWifiLine(char* line) {
if (strncmp(line, "OPEN ", 5) == 0) {
char* resp = line + 5;
char correctHexResp[41];
uint8_t *key = (uint8_t*)"PASSWORD_HERE";
Sha1.initHmac(key,11);
Sha1.print(challenge);
uint8_t* hash = Sha1.resultHmac();
for (int i=0; i<20; i++) {
correctHexResp[i*2+0] = ("0123456789abcdef"[hash[i]>>4]);
correctHexResp[i*2+1] = ("0123456789abcdef"[hash[i]&0xf]);
}
correctHexResp[40] = '\0';
if (strcmp(resp, correctHexResp) == 0) {
wifiPrint("OPENOK\n");
toggleDoor();
} else {
Serial.println("fail. got vs. want:");
Serial.println(resp);
Serial.println(correctHexResp);
Serial.println(challenge);
}
generateChallenge(); // prevent replay attacks / guessing
return;
}
Serial.print("unhandled wifi line command: ");
Serial.println(line);
}
int lineBufHasSuffix(char* suf) {
int l = strlen(suf);
for (int i = 0; i < l; i++) {
if (lineBuf[(lineBufLen-l+i+lineBufCap)%lineBufCap] != suf[i]) {
return 0;
}
}
return 1;
}
void wifiPrint(char* s) {
SerialRNXV.print(s);
Serial.print("WIFI: ");
Serial.print(s);
if (strstr(s, "\n") == NULL) {
Serial.print("\n");
}
}
void toggleDoor() {
wifiPrint("TOGGLE_GARAGE\n");
digitalWrite(togglePin, HIGH);
delay(200 * ms);
digitalWrite(togglePin, LOW);
}
void generateChallenge() {
int i;
for (i = 0; i < challengeLength; i++) {
challenge[i] = char(random('A', 'Z'+1));
}
challenge[challengeLength] = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment