Hacking Segway keys

Ingredients:

  1. Dallas Semiconductor DS1993L 4kb NVRAM iButton
  2. Dallas Semiconductor DS1402D-DR8 Blue Dot Receptor (Serial)
  3. Dallas Semiconductor DS9097U-009 Universal 1-Wire COM Port Adapter
  4. Dallas Semiconductor DS9093A iButton angled FOB mount (blue)
  5. Dallas Semiconductor 1-Wire SDK for Windows (includes OneWireViewer)
  6. Segway, LLC Fancy Scooter, with keys
You can order the above parts here (minus the segway. You can order that here).

The folks at segway have done a good job of creating a secure rider authentication system, along with a fairly easy mechanism to copy and alter the keys themselves. So these pages talk about "hacks", but in reality, the capability was designed in by the segway engineers from the beginning. Based on this, I am optimistic that in the near future we will see some tools and extended functionality from the team at segway.

The segway keys are standard Dallas iButtons. 4kb of NVRAM. Only 16 bytes are actually used. There is no security at the 1-Wire level, so you're free to read/write any page. That leaves plenty of room for hacker-added-value (You could, conceptually, use one of the Java iButtons to keep track of how many times you power-up your segway).

Of the 16 bytes that are loaded onto each button, the first two bytes are an inverted crc16 checksum of the remaining 14 bytes. The following 11 bytes are the key itself. The last three bytes are some simple parameters that control the segway's behavior:

  crc hi   crc lo  ignition key code
  94       b6      10 0c 16 83 15 58 1f f8 16 1b a3

  translate  unknown  rotate
  19         00       b0     (red key)
  10         00       90     (yellow key)
  0c         00       50     (black key)

Changing the parameters is fun. I like setting the translate speed to 0xFF, and the rotate speed to 0x00. It pretty much guarenties broken limbs because you can haul-butt in a straight line, but can't turn very well (I call this "SUV" mode).

Here are some sample warez to get you started:

#include 

unsigned int crc16(unsigned char *b, int len)
{
   int i,j,k;
   unsigned char c;
   unsigned int r = 0;

   for (k = 0; k < len; k++) {
      c = b[k];
      for(i=0;i!=8;c>>=1,i++)
      {
          j=(c^r)&1;
          r>>=1;

          if(j)
             r^=0xa001;
      }
   }
   return r;
}

int main (int argc, char *argv[])
{
   unsigned char buf[] = {0x94,0xb6,0x15,0xdc,0x16,0x23,0x05,0x42,0x2d,
                          0xf1,0xaf,0x01,0x05,0x19,0x00,0xb0};
   int i, crc;
   unsigned int p1, p2, p3;

   if (argc < 2) {
      printf("%s [translate velocity] [00] [rotate velocity]\n", argv[0]);
      exit(1);
   }

   sscanf(argv[1], "%x", &p1);
   sscanf(argv[2], "%x", &p2);
   sscanf(argv[3], "%x", &p3);

   buf[13] = p1;
   buf[14] = p2;
   buf[15] = p3;

   crc = ~crc16(&buf[2], 14);
   buf[0] = (crc & 0xff00) >> 8;
   buf[1] = crc & 0xff;

   for (i = 0; i<16; i++)
      printf("%x ", buf[i]);

   printf("\n");

   return 0;
}

Please don't hurt yourself.