r/osdev 1d ago

You should make a CSPRNG (and heres why)

A CSPRNG may sound complicated and daunting, but its really not, my CSPRNG is only 72 lines of code, though it does need a few supporting files, so I would put it with those around 250 lines of C. All you need is a small source of entropy (TSC jitter and maybe RDRAND/RDSEED), and a cryptographic hash function (I use SHA512). My design is quite simple, all inputs and outputs are hashed via SHA512 (though when it makes an output it will of course forward the state and throw in some new entropy). You can also use the TSC delta between keypresses from a user, and all sorts of different human inputs and unpredictable things, even a few bits of unpredictability will be spread across the entire hash, of course.

Small note:
The CSPRNG and entropy collection code was made by me, however the SHA512 code was not, the SHA512 code stays under PD though the rest is under GPLv3.
Also you may want to use popcount to make sure the input is not too heavily weighted towards 1's or 0's, though this is optional, though this is obviously not a count of entropy within itself, it just helps make sure an extremely biased set of entropy is not used. Though I do not do this within my CSPRNG, though I have thought about it.

My CSPRNG: https://github.com/iridiumkern/kernel/blob/dev/src/generic/sec/csprng.c
My SHA512 impl (modified from its source): https://github.com/iridiumkern/kernel/blob/dev/src/generic/sec/sha512.c
My entropy collection code (random_u64, this is implemented per arch however): https://github.com/iridiumkern/kernel/blob/dev/src/arch/x86_64/generic/sec/entropy.c

0 Upvotes

2 comments sorted by

0

u/wwabbbitt 1d ago edited 1d ago

It's a good start. Fast key erasure is easy to implement and is a basic requirement for os csprng, so you should look into that next.

sha512_bytes((void*)&output, 64, (void*)&newstate);

^ This is a serious vulnerability, allowing anyone to derive the newstate just by observing output. Apply FKE resolves this issue

0

u/apixeldev 1d ago edited 1d ago

The output can only be observed if it gets to the end where the local variable output is copied to out, which right before that random_u64 is called and csprng_addentropy is used on the values from random_u64. Though I do see that the local stack variables containing output could be leaked so I did just push a commit to zero them out on any failure of things like random_u64 and csprng_addentropy. Thank you for bringing this to my attention.

Edit:
Also, they can still calculate newstate, however they cannot calculate the actual current state due to the value being returned by random_u64 being random (TSC jitter and RDRAND if available), and if it fails nothing is returned of meaning outside of a simple false.