smallwing Thanks a lot, I cannot believe I missed that section. It did indeed answer all my questions, except for whether GrapheneOS does anything to prevent apps from storing unencrypted data. I guess not, since it would probably have been in the GrapheneOS documentation otherwise. That is a bit unfortunate, since this means I need to trust all apps I run to be properly coded on a much higher level than I would need to on Linux.
Just to summarize my findings, and answer my own questions so the next person doesn't have to dig through the documentation:
To protect the synthetic password with the LSKF, LockSettingsService first stretches the LSKF by passing it through scrypt, targeting a time of about 25 ms and a memory usage of about 2 MiB. Since LSKFs are usually short, this step usually does not provide much security. The main layer of security is the Secure Element (SE) or TEE-enforced ratelimiting described below.
Okay, so the security provided by the disk encryption is deliberately weakened a lot, 1000 ms down to 25 ms (giving attackers a speed advantage of 40x) and 500 MB down to 2 MB (giving attackers an additional speed advantage of 250x, so total speed advantage of 10000x), compared to Linux. Nothing that cannot be compensated against, one just have to have a password that is two words longer, but that is already unfortunate since one has to type ones password every time the phone screen locks, not just at boot time like on Linux where you can have a separate simpler screen password.
Unless I choose to trust the secure element "blackbox" solution of course, which I won't.
Android 7.0 and higher supports file-based encryption (FBE). FBE allows different files to be encrypted with different keys that can be unlocked independently. These keys are used to encrypt both file contents and file names. When FBE is used, other information, such as directory layouts, file sizes, permissions, and creation/modification times, is not encrypted.
And:
However, except for filenames, fscrypt does not encrypt filesystem metadata. ... fscrypt does not protect the confidentiality of non-filename metadata, e.g. file sizes, file permissions, file timestamps, and extended attributes.
Okay, so true file sizes for each file is stored unencrypted. There is no attempt to conceal true file sizes, making file confirmation attacks trivial. There is also no attempt to conceal directory structure, number of files in each directory, and so on, like I said.
This makes the disk encryption basically useless to someone who really needs it, think a whistleblower, or political activist in a repressive regime, since it won't conceal the identity of files that has ever been posted on the web. Anyone who seizes your device can tell what files ever posted on the internet you have on your device, without knowing your PIN or password, without unlocking your device.
Would be interesting to know if GrapheneOS has plans to improve the disk encryption solution. It is unfortunate it is this far behind in security compared to LUKS2 and even VeraCrypt.
fscrypt is not guaranteed to protect confidentiality or authenticity if an attacker is able to manipulate the filesystem offline prior to an authorized user later accessing the filesystem.
So, same problem as all other file based disk encryption schemes. For block based disk encryption such as LUKS2 or VeraCrypt, the XTS mode is supposed to give some level of protection against this, but only because all metadata also gets encrypted.
Sources for the quotes:
https://source.android.com/docs/security/features/encryption/file-based
https://www.kernel.org/doc/html/v6.0/filesystems/fscrypt.html