cryptsetup backend safe with multithreading?

431 Views Asked by At

Is there a crypto backend for cryptsetup that either is always thread safe, or can be easily used (or even modified, preferably with minimal effort) in a thread safe manner for simply testing if a key is correct?

Background and what I have tried:

I started by testing if I could modify the source of cryptsetup to simply test multiple keys using pthreads. This crashed, I believe I used gcrypt initially. Eventually I tried all of the backends available in the cryptsetup stable source and found that openssl and nettle seems to avoid crashing.

However, my testing was not very thorough and even though it (nettle specifically) does not crash, it seems that it does not work correctly when using threads. When using a single thread it always works, but increasing the number of threads makes it increasingly likely it will silently never find the correct key.

This is for brute forcing LUKS devices. I am aware the pbkdf slows it down to a crawl. I'm also aware the key space of AES cannot be exhausted even if the KDF was not there. This is just for the fun of making it in a network distributed and multithreaded manner.

I noticed in the source of cryptsetup (libdevmapper.c):

/*
 * libdevmapper is not context friendly, switch context on every DM call.
 * FIXME: this is not safe if called in parallel but neither is DM lib.
 */

However, it is possible I'm simply not using it correctly.

    if(!LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, key, strlen(key), &cd->u.luks1.hdr, &vk, cd)) {
            return 0;
    }

Each worker thread does this. I only call crypt_init() and crypt_load() once before the worker threads start up and pass them their own separate copy of the struct crypt_device. vk is created locally for each attempt. The keys are simply fetched from a wordlist with access control by a mutex. I found that if each thread calls these functions (crypt_init and crypt_load) every time, it seems to crash more easily.

Is it completely incorrect to try start removing and rewriting the code that uses dmcrypt? In LUKS_endec_template() it attaches a loop device to the crypto device, and creates a dm device which it eventually gives to open(), which it then gives the fd of to read_blockwise(). My idea was to simply skip all of that since I don't really need to use the device except to verify the key. However, simply opening the crypto device directly (and give it to read_blockwise()) does not work.

0

There are 0 best solutions below