Edit the wireless regdb regulatory.db

Category: Gentoo Tags: wireless regulatory db, kernel

Howto adjust your wireless regdb a.k.a regulatory.db used by linux kernel.

In a former blog post I described how to edit the regulatory.bin used by crda.
Since then a few things have changed. Most important recent linux kernels load the regulatory db themself. The construct of udev rule and crda has become obsolete.
But for the kernel to load the regulatory db it has, by default, to be signed with a certificate included in the kernel.

You can configure your kernel in expert mode to accept a unsigned regulatory db.

Also wireless-regdb tools now use python3.

So the tasks are:

  • sign the db with our private key
  • generate a certificate based on our private key
  • supply the kernel with our certificate


Sign the db with our private key

The regulatory db is installed via net-wireless/wireless-regdb ebuild. Normally db files and everything else is just copied.
We hook into the emerge process to regenerate the db and sign it with our private key.

Of course first you should extract net-wireless/wireless-regdb adjust db.txt to your needs and create a patch, which is stored in etc/portage/patches/net-wireless/wireless-regdb/.

To hook into the emerge process we supply the script etc/portage/env/net-wireless/wireless-regdb. It will be sourced by emerge and callback functions get executed. Look into the older post for more details.

#!/usr/bin/env bash

export REGDB_PRIVKEY="rapna.key.priv.pem"
export REGDB_PUBKEY="rapna.key.pub.pem"
export REGDB_PUBCERT="rapna.x509.pem"
export REGDB_AUTHOR="rapna"

Almost the same as in the old version, but lets get to it.
Global variables are set with export. I had issues with them not defined so I do it this way ... maybe it is not necessary.

post_src_prepare() {
    if [ -f "/etc/wireless-regdb/$REGDB_PRIVKEY" ]; then
        einfo "Found private distro key"
        cp "/etc/wireless-regdb/$REGDB_PRIVKEY" .

        if [ -f "/etc/wireless-regdb/certs/$REGDB_PUBCERT" ]; then
            einfo "Found distro certificate"
            cp "/etc/wireless-regdb/certs/$REGDB_PUBCERT" .
        fi
    fi
}

post_src_prepare is executed after sources are extracted and patches are applied. If there is already a private key and/or a certificate in the host system we copy it into the build directory.

post_src_compile() {
    if [ -f $REGDB_PRIVKEY ]; then
        einfo "Using private host key for signing"
    else
        einfo "Generate private host key for signing"
        make $REGDB_PRIVKEY
    fi

    if [ -f $REGDB_PUBCERT ]; then
        einfo "Using distro certificate for signing"
    else
        einfo "Generate distro certficiate host key for signing"
        openssl req -new -key "$REGDB_PRIVKEY" -days 36500 -utf8 -nodes -batch \
            -x509 -outform PEM -out "$REGDB_PUBCERT" \
            -config <(cat <<-EOF
                [ req ]
                distinguished_name = req_distinguished_name
                string_mask = utf8only
                prompt = no
                [ req_distinguished_name ]
                commonName = $REGDB_AUTHOR
EOF
            )
    fi

    make sha1sum.txt
    make regulatory.bin
    make regulatory.db
    make regulatory.db.p7s
}

post_src_compile is executed after regular compiling, which doesn't happen in this ebuild.
If there is a private key use it otherwise create it. Same goes for the certificate.
The generation of the certificate is a bit more complex. It is vital to generate a pem encoded x509 certificate based on the private key. Finally use the make file and generate the checksum, the obsolete regulatory.bin, regulatory.db for the kernel and regulatory.db.p7s, the signature of regulatory.db.
In opposite to the old post there is no need to patch the tools as python3 is supported.

post_src_install() {
    if [ -f $REGDB_PUBKEY ]; then
        einfo "Install public key for signed regulatory.bin"
        insinto /etc/wireless-regdb/pubkeys
        doins $REGDB_PUBKEY
    fi

    if [ -f $REGDB_PRIVKEY ]; then
        einfo "Install private distro key"
        insinto "/etc/wireless-regdb"
        doins $REGDB_PRIVKEY
    fi

    if [ -f $REGDB_PUBCERT ]; then
        einfo "Install distro certificate"
        insinto "/etc/wireless-regdb/certs"
        doins $REGDB_PUBCERT
    fi
}

Finally in post_src_install install the generated public key, the private key and the certificate. The public key is obsolete.
regulatory.db and regulatory.db.p7s have been installed in lib/firmware, that's where the kernel will look for them.

So far so good

  • adjusted regulatory.db ... check
  • signed with private key ... check
  • put everything in place ... check

Download wireless-regdb script


The Kernel

The kernel sources ship with certificates and when the kernel is compiled they are statically included.
To include our own certificate, we have to hook into the emerge process.
As I use sys-kernel/gentoo-sources, I have to supply etc/portage/env/sys-kernel/gentoo-sources.

I already have the file by that name, cause I compress the kernel sources as squashfs as described here.
Anyway I will discuss only what is needed for the certificate.

#!/usr/bin/env bash
# /etc/portage/env/sys-kernel/gentoo-sources

pre_src_install() {
    for cert in "${EROOT}"/etc/wireless-regdb/certs/*.x509.pem ; do
        if [ -e "$cert" ]; then
            openssl x509 -in "$cert" -inform PEM &>/dev/null;
            if [ $? -eq 0 ]; then
                file=`basename "$cert"`
                einfo "Adding wireless certificate to kernel sources ($file)"
                inc=${file%.x509.pem}
                openssl x509 -in "$cert" -inform PEM -outform DER | xxd -i -c 8 > "${WORKDIR}/linux-${KV_FULL}/net/wireless/certs/${inc}".hex
            fi
        fi
    done
}

pre_src_install hook is used. All files in etc/wireless-regdb/certs/ ending with x509.pem are checked and if they are pem encoded x509 certificates they will recoded in DER binary format and hexdumped for use in header files. This is how the kernel needs the certificate.

I use xxd for hexdumping. xxd belongs to vim, which is not everyones favourite. Be sure to check if you got xxd or use an alternative!

Finally the certificates are copied into the kernel sources. Whether you compress the sources afterwards or not, the certificates will be installed alongside the kernel sources and included when the kernel is compiled.

That's it for the kernel.
When you build your kernel and boot it, you should see something similar to this in your log:

notice kernel: cfg80211: Loaded X.509 cert 'rapna: 00ff63db13b1b338bd'

With the certificate included in the kernel, the kernel will now load and accept your self signed regulatory.db.

Download gentoo-sources script