# Reverse-engineering Security+ garage-door rolling codes

> A weekend that turned into a project: a clean-room software reimplementation of the Security+ and Security+ 2.0 garage-door rolling-code systems, framed as an RF reverse-engineering exercise.

By Jeff Mixon, published 2023-09-14. Canonical: https://www.jeffmixon.com/post/garage-door-rolling-codes-reversed/

## A familiar shape

A garage door opener is the smallest possible interesting RF system. You
have a transmitter the size of a key fob, a receiver in a fixed location,
and a short message that has to be unforgeable enough that someone
listening on the street can't open your garage with last week's recording.
The fact that the messages *change every time you press the button* is
the whole reason any of this is hard.

That last property is the **rolling code**. The Chamberlain / LiftMaster
"Security+" family — both the original and the second-generation
Security+ 2.0 — is one of the dominant implementations of it. There is
existing public research, there are public-but-fragmentary
implementations, and there is a long tradition of hobbyists who have
worked through pieces of the system. I wanted my own clean-room
reimplementation in software — not to attack anyone's garage, but to
genuinely understand the mechanism end to end and to have a software
artifact I could read.

## Methodology

This was deliberately a **software-only** project: clean-room
re-derivation in code from public information and signal-level analysis,
not from leaked or proprietary sources. The methodology was the usual RF
reverse engineering loop:

1. **Capture.** A software-defined radio sniffing the on-air frames at
   the manufacturer's nominal frequency.
2. **Demodulate.** Identify the modulation scheme and the symbol rate;
   recover bits.
3. **Frame.** Identify framing markers, payload boundaries, and any
   per-frame structure that is independent of payload contents.
4. **Diff.** Capture many successive presses from the same fob. The
   bits that change every time are the rolling-code carrier. The bits
   that don't are device identity, command, or framing.
5. **Implement.** Write the generator. Verify that successive outputs
   match successive captures.
6. **Read back.** Confirm the implementation against the public literature
   on the family. Note any deltas — those are usually places one or the
   other is wrong about a detail.

That loop is the same whether you are reverse-engineering a garage door,
a tire-pressure sensor, a weather station, or a wireless thermometer.
Once it is muscle memory, the work is finding the right thing to point
it at.

## What the rolling-code part actually is

I'm going to keep this abstract on purpose — both because the existing
public literature already covers Security+ in detail for anyone who wants
the specifics, and because a personal-website blog post is not the right
place to publish a complete how-to.

The shape of the construction is: a counter that increments per press, a
device identity, a fixed key, and a transform that mixes the three into
the bits actually transmitted. The receiver maintains a windowed view of
acceptable counters and rejects anything outside the window. A captured
frame is only useful for as long as the receiver has not yet seen anything
later than it; the moment the legitimate fob is pressed, every earlier
capture is dead.

The interesting failure modes — the ones that have driven later research
into this family — are around what happens at the edges of that window:
how big it is, how it behaves on resync, how robust the transform is to
known plaintext. Those edges are why Security+ 2.0 exists and why this
remains an active area of hobbyist research.

## What I got out of it

A clean Python implementation that generates and verifies frames against
captures, plus a working knowledge of a non-trivial RF protocol family
that I keep finding useful — the structure of "device ID + rolling
counter + transform + window" recurs in a remarkable number of cheap
wireless devices once you have learned to recognize it.

The software lives in a private repository for now; the writeup is here.

## Closer

RF reverse engineering at the hobbyist level used to require
oscilloscopes and logic analyzers and a soldering iron. SDR collapsed
most of that into a USB stick and a Python notebook. The barrier to
*looking* at the bits in the air is essentially zero now. The barrier to
*understanding* them is still doing the work — capture, demod, frame,
diff, implement, read back. That loop is exactly as old as RF and
exactly as rewarding.
