[Android Q&A, Help & Troubleshooting] robberknight:
Ok, after some work I figured out a way to do it.

You need a rooted phone and an adb connection to it. I tried this with CM13, other versions or roms will probably differ slightly in the parameters, so you should have basic linux shell skills.

The first step is to get a cryptsetup binary compiled for the architecture of your phone. You can compile it yourself from sources like https://android.googlesource.com/platform/external/cryptsetup/+/master or https://github.com/nelenkov/cryptsetup.

But I was lazy and installed LUKS Manager from the Play store. It contains a version of cryptsetup compiled for ARM. Extract it like this:

adb root
adb shell
setenforce 0
cd /data/app/com.nemesis2.luksmanager-1
unzip base.apk
cp assets/lm.cryptsetup /data
chmod 755 /data/lm.cryptsetup

Now we have the cryptsetup binary lying in /data/lm.cryptsetup. You can now uninstall LUKS Manager again as we don't need it anymore.

Now is a good time to back up the contents of your sd card. Then insert it into the phone and format it as portable if you don't have done that yet.

The next step is to figure out the device node of your sd card. You don't easily see this when looking at the mounts as vold hides it from us. So go to /dev/block and look at the device nodes. You are looking for a mmc device that has just one partition (just one extra node with ...p1). Then open it with fdisk and look if the size matches your sd card. On my phone it was mmcblk1.

Now we split the sd into two partitions: one very small (like 10MB) fat32 partition and the rest as an encrypted partition with LUKS header. This is to trick vold into helping us making the encrypted partition visible to regular Android apps.

Run fdisk for the mmc device (not the one with ...p1, the one without) and delete the existing partition. Create two partitions as outlined above. Set the type of the small partition to "c" (fat32) and the type for the large one to "8e".

It should look like this:

# fdisk /dev/block/mmcblk1

The number of cylinders for this disk is set to 3902128.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems.

Command ('m' for help): p
Disk mmcblk1: 127.8 GB, 127864930304 bytes
4 heads, 16 sectors/track, 3902128 cylinders
Units = cylinders of 64 * 512 = 32768 bytes

Device Boot Start End Blocks Id System
mmcblk1p1 33 352 10240 c Win95 FAT32 (LBA)
mmcblk1p2 353 3902128 124856832 8e Linux LVM

Now we format and set up the partitions. Replace "mmcblk1" with the device node on your device.

mkfs.vfat /dev/block/mmcblk1p1
/data/lm.cryptsetup -i 5000 -h sha256 luksFormat /dev/block/mmcblk1p2
/data/lm.cryptsetup luksOpen /dev/block/mmcblk1p2 sdcrypt
mkfs.ext2 /dev/mapper/sdcrypt

The mkfs.ext2 may take a while. I'm using ext4 here as it's usually faster for reads than f2fs. I use the sd mostly for long-term media storage, so reads are more important than writes.

When you are done reboot your phone.

When it is up again check your sd card storage. It should be a bit below the size you chose for the small fat32 partition, e.g. around 9 MB. If that worked, then vold has mounted the small partition and made it available to regular Android apps.

Connect with adb and check the volume id of the fat32 partition like this:

blkid /dev/block/mmcblk1p1

Mine is "5824-FB9F". You need to adapt the following commands and insert your volume id.

Now we open the crypto container and mount the partition over the mountpoint of the small fat32 partition. This way we reuse the work that vold has just done and switch out the partitions without it noticing.

These are the commands you need to issue on a root shell to do the mount:

echo "your_secret_password" | /data/lm.cryptsetup luksOpen /dev/block/mmcblk1p2 sdcrypt
mount /dev/mapper/sdcrypt /mnt/media_rw/5824-FB9F -t ext4 -o nosuid,nodev,noexec,noatime,nodiratime,context=u:object_r:vfat:s0
am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///storage/5824-FB9F

This needs to be done on after each reboot. I use tasker for this, but there are plenty of other methods. The script contains your password. So make sure that it is stored on the encrypted /data partition and not somewhere insecure.

On the first mount I had to fix the permissions like this:

chown -r media_rw:media_rw /mnt/media_rw/5824-FB9F
chmod 770 /mnt/media_rw/5824-FB9F

Have phun!