Arduino Garage Door Opener Is Security Minded

Arduino garage door opener

Do it yourself garage door openers must be all the rage nowadays. We just got word of another take on this popular idea. [Giles] was commissioned by his friend to find a way to control the friend’s garage door using a smart phone. The request was understandable, considering the costly garage door remote and the fact that the buttons on the expensive remote tended to fail after a while. The inspiration for this project came from some YouTube videos of other similar projects. Those projects all paired an Arduino with a Bluetooth headset in order to control the door from a mobile phone. [Giles] understood that while this would get the job done, it wouldn’t be very secure. Bluetooth headsets typically connect to mobile phones using a four digit PIN. Many of them have known default PINs and even if the default is changed, it wouldn’t take very long to guess a four digit PIN. [Giles] knew he had to find a more secure way.

While WiFi was an option, [Giles] decided that having the garage door hooked up to the internet would likely be a security risk, even if it did offer some potential interesting use cases.  He therefore opted to stick with Bluetooth, but decided to use the Seedstudio Bluetooth shield instead of a basic headset. The electronics are relatively simple. [Giles] simply plugged the Bluetooth shield into an Arduino Uno. [Giles] did have one problem with the Bluetooth shield though. The Bluetooth module did not accept many standard AT commands. He needed a way to force a disconnect of a mobile device if it failed authentication. After digging around, he discovered that the module had some extra exposed pads that he could likely use to accomplish that goal. The only problem was that they were expecting a 3.3V signal, and the Arduino works at 5V. The solution was simple. He setup a basic voltage divider using two resistors. This lowered the 5V signal from the Arduino to the required 3.3V. This provides the communication functionality to the mobile phone. He then realized that he could use a simple 12V automotive relay to control the garage door. To control the relay, he used the Freetronics relay control shield. The end result is a relatively simple stack of shields hooked up to a relay.

For the smart phone interface, [Giles] started out by trying to write a native Android application. Having little experience in Android development, he soon realized that it was going to take him longer than anticipated to get anything usable this way. He then decided to use SL4A. SL4A provides a scripting environment for Android and supports several different scripting languages. [Giles] was then able to write a Python script that can be executed on the smart phone. Many people would be tempted to write a really simple script that would just open the door and connect without any real thought about security. After all, this is a one-off obscure garage door opener. Security through obscurity! [Giles] is smarter than that.

He instead implemented a challenge handshake authentication mechanism between the Python script and the Arduino. This would ensure that users are authenticated before permitting commands to be executed, and also help prevent replay attacks. The process works like this. First the smart phone connects to the Arduino. The Arduino then generates a pseudo-random string and calculates the expected response, based on a pre-shared key. The phone then receives the string and sends back the appropriate response. If it doesn’t match, the Arduino disconnects the phone. If it does match, the phone then sends back a request for a different pseudo-random command challenge string. Once the phone receives this new string, it is able to use that string in conjunction with a second pre-shared key to generate a one-time use command. Assuming it was calculated correctly, the Arduino will then run the command to open or close the door. If it doesn’t match the phone gets disconnected. All of this is to help prevent replay attacks. Any attacker watching the airwaves would not be able to simply record the signals or commands and play them back. This is because every time the authentication and commands are transmitted, they must be different based on the pseudo-random seed.

While everything seems to work mostly fine, the Arduino tends to crash after about six door cycles. [Giles] believes this may be caused by the MD5 library he is using but has so far been unsuccessful in trying to fix this bug. He also thinks his Python script is messy and somewhat unstable. He’s decided to publish his programs to the internet in hopes that someone else may have the time and drive to figure out what’s going on.

13 thoughts on “Arduino Garage Door Opener Is Security Minded

  1. Seems like a good job for a pi, pogo plug, or one of many hackable routers available. Get a USB bluetooth dongle and you are good to go. As to putting it on the internet? Well using SSH with a shared keys should be secure enough for anybody’s garage. With a Pi or router you could add features like a web cam that would take pictures of the driveway when the door is told to be open or even use OpenCV and a detect the car and combine it with the BLE to add an auto open feature to the door if one was wanted.

  2. That library seems to return a pointer to a locally defined char array in MD5::make_hash. I generally dont do that if I want my code to work…

    MD5::make_digest does return a pointer to some malloc’d memory, which you need to free() once you’re finished with it if you like not having memory leaks. That could be the cause of you running out of memory as most of it will be taken up by all those C++ Strings anyway.

    Good luck!

  3. Assuming this https://github.com/tzikis/ArduinoMD5/blob/master/MD5.cpp is the MD5 library he is using, I’d think this snippet might be the offending code:

    String createCMDMD5Hash(String input, String CMD)
    {
    char toHash[50];
    String(cmdpass + CMD + input).toCharArray(toHash, 50);
    unsigned char* hash=MD5::make_hash(toHash);
    char *md5str = MD5::make_digest(hash, 16);
    return md5str;
    }

    He uses 2 functions from the MD5 that both return a pointer to a buffer. Both functions contain SERIOUS flaws.

    The make_hash() function returns a pointer to a buffer to a local, non-static buffer, which means it’s on the stack, and out of scope after returning from the function. While this won’t cause a memory leak, the stack space will quickly be used for other functions, which will corrupt the data. If it works properly now, that is mostly due to chance. Even if the very next function copies the data and that call doesn’t corrupt it, it would be corrupted if you have any enabled interrupts, if an ISR is called at just the right (or wrong) moment.

    The other function isn’t necessarily wrong, but he is using it wrong. This function malloc()’s the memory needed for the return buffer, which [Giles] never free()’s. He could either call free() on the pointer after he used the returned data, or (arguably better) change both functions to accept a pointer to a static buffer for the return data, avoiding the use of malloc() altogether.

  4. Hi all. Like sparkygsx says, static memory allocation can be a very good thing for stability. The memory can be a global (not preferred!), a static variable in a function (tidy provided you never want 2 simultaneous accesses) or nicely wrapped into an instance of a class. I do hard real-time programming at work (power electronics control, where glitches are A Bad Thing) and malloc()/new are not your friends when the code needs to run for an infinite number of cycles.

  5. And this is why I put it out to the world! I’ll be reviewing the troublesome code to try and fix the memory issue now based on the previous comments.

    For anyone wondering why I used an arduino rather than a Pi or similar? Simple… I had the Arduino spare, and all my Pis are busy running various other things, such as my solar powered bitcoin miner (which is inefficient, but hey, free energy for it…)

    1. An Arduino seems just right for this job – there doesn’t seem to be a need for 32 bit power or an operating system. If you want some enhanced features (eg recognize your car’s license plate and open the door automatically (yes, I know, not very secure, but pretty cool, no? (Yay nested parenthesis!))) then a bit more grunt would probably be advisable.

  6. I still think WiFi access is something to consider.

    Some routers can allow WiFi access from specific MAC addresses (The friends phone needs to be nearby, directly connected to the router.)

    Routers can also block access from the network to the internet, based on MAC addresses (this isolates the garage door controller from the internet, while allowing the phone internet access.) (Also useful for isolating XP computers from the internet.)

    1. MAC based blocking is a convenience/management feature, it has practically nothing to do with security. You can spoof MAC addresses dead easy. And once you’re able to be close enough for Wifi-Reception once when the door is opened, you know the MAC you have to spoof.

      1. Spoofing the MAC is the second step (and is trivial). The first is that you have to be close enough to connect. The third step is that you have to get past the WPA2/AES security.

        The first and third steps are serious obstacles, even for serious hackers. I doubt the typical burglar is going to bother with any of this.

  7. I went with the WiFi WPA2/AES option and TinyWebServer. That way I could set it up to accept commands via different URL’s (I guess it’s a REST interface) from any device that is authorised to connect to our home WiFi.

  8. Didn’t understand how does it work… I red that the Arduino hosts a little web page on the local network which you can access from any other device on the network, such as your smartphone, just like a normal website. When you input your password, the Arduino triggers a relay that acts like a wired garage door remote that you often see next to the internal door. Buttt… why complicate. Just for using a smartphone instead a garage door opener remote control? What’s the difference?

    1. I would take a guess that this is at least a little more secure than hosting a local webpage on the arduino. After looking at the SL4A script it will be more difficult to capture and crack the password due to how it is handled. The SL4A script could also be cleaned up a little by creating a class to for the various dialog / alert boxes.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.