google / mundane

Mundane is a Rust cryptography library backed by BoringSSL that is difficult to misuse, ergonomic, and performant (in that order).
MIT License
1.07k stars 46 forks source link

Add block ciphers #5

Open joshlf opened 6 years ago

joshlf commented 6 years ago

Open questions:

etrexel commented 5 years ago

Hello, I am interested in AES-CBC and would be willing to give it a crack. Have you guys done anything on the block cipher front recently?

ojhunt commented 5 years ago

You could do something absolutely brutal:


trait BlockCipher {
...
}
trait Counter {}
trait PaddingSafeCounter :Counter {}

pub struct CBCCounter {}
pub struct GCMCounter {}

impl Counter for CBCCounter {}
impl Counter for GCMCounter {}
impl PaddingSafeCounter for GCMCounter {}

struct CipherContext<Cipher: BlockCipher, CounterMode: Counter> {
...
}

impl <Cipher, CounterMode> CipherContext<Cipher, CounterMode>
where Cipher: BlockCipher, CounterMode:PaddingSafeCounter {
    fn new_with_padding(_c:&Cipher,_m:&CounterMode)  {}
}

impl <Cipher, CounterMode> CipherContext<Cipher, CounterMode>
where Cipher: BlockCipher, CounterMode:Counter {
    fn new_without_padding(_c:&Cipher,_m:&CounterMode)  {}
}

This is just for illustrative purposes -- but you can reasonably easily do something like this to prevent mode misuse.

joshlf commented 5 years ago

Hey @etrexel, sorry for taking so long to get to this.

Since I wrote this issue, I came to realize that this is going to be much harder than I'd originally thought. Now, that statement has some caveats, so let me try to explain my thinking:

Mundane's first goal is to be as misuse proof as possible. Block cipher-based cryptosystems are absolutely rife with opportunities for misuse, stemming mostly from cipher modes and initialization vectors. What that means is that, just like the other primitives we already provide, if we're going to provide block ciphers, we need to figure out a high-level API that is both misuse-resistant and also flexible enough to serve developers' needs. It can't just be "here's a aes_encrypt_block now have fun" because that leaves all of the subtle hard parts up to the developer. We'd much prefer something like "here's a primitive that takes a plaintext and gives you a ciphertext, and makes all of the cipher mode choices and does all of the IV generating for you."

Now, such a thing wouldn't be too hard to build. It would require some very careful thought about the safety properties of the various primitives (e.g., which block ciphers/modes are safe to be used with an incrementing IV? Which ones are safe to be used with randomly generated IVs? Since we're a stateless library, is there anything we can do to prevent IV reuse across multiple runs of a program?), but it's within the realm of possibility.

However, where this really gets tricky is serving developers' needs. We would like for Mundane to be able to serve as the basis for higher-level crypto implementations, and that means that we can't simply design with the goal of making a clean API. It also means that whatever we build has to be compatible with existing protocols. E.g., protocols like TLS and SSH specify very precisely how cipher modes and IVs are to be handled, so we have to, at the very least, support whatever they mandate.

As far as I can tell, there are a few ways we could accomplish this, in descending order of preference:

The first thing that's required here is a comprehensive survey of the landscape. Ideally, we could get:

Anyway, very long winded answer, but the TLDR is that this is a lot harder than I originally expected. To be clear, this is not meant to scare you off - if, given that diatribe, you're still interested, then I absolutely encourage you to try it. I just don't want to give a false impression that this is just going to be a matter of exposing some primitives from BoringSSL and calling it a day. And now that you know what you've gotten yourself into, welcome to Mundane and thanks for your interest in contributing! :P

PS: Feel free to reach out by email if you'd like to get into more details beyond what can reasonably go in an issue comment thread.