Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eax: Introduce a streaming API #214

Merged
merged 7 commits into from
Sep 30, 2020
Merged

Conversation

Xanewok
Copy link
Contributor

@Xanewok Xanewok commented Sep 9, 2020

Introduces a stream module that implements EaxStream, which is the streaming variant of the regular Eax implemented here.

This can be useful for two reasons, in addition to having the existing one-shot-like API:

  1. The associated data can be processed separately
  2. The protected data can be processed in a streaming fashion, rather than requiring it to be entirely allocated and contiguous.

I'm trying to reuse the EAX implementation for use in Sequoia (Rust OpenPGP implementation) but unfortunately I need the streaming API variant for that.

Because the newly-introduced in-place API can be somewhat easily misused, I tried to mimic a linear type, forcing the user to explicitly consume and handle the resulting value after decryption. With std feature enabled, it aborts the process using a drop bomb pattern, unless it's forgotten by the EaxStream::finish associated function.

Note that this changes the existing Eax implementation by first performing the decryption in-place and then checking against the expected tag, rather than scanning the ciphertext first to calculate tag and then decrypting if the tags match. I have to admit that I did that to share more of the implementation and leverage the testing framework test both implementations but I can revert that change if needed.

Let me know what you think about this and if this is something you'd consider merging in one form or another.

@Xanewok
Copy link
Contributor Author

Xanewok commented Sep 9, 2020

codecov.io check fails with

Please provide an upload token from codecov.io with valid arguments

@tarcieri
Copy link
Member

tarcieri commented Sep 9, 2020

Some previous discussion on #132.

One tricky naming thing here is we intend to implement STREAM, a provably secure segmented AEAD (a.k.a. OAE) construction designed by Phil Rogaway. This can be implemented generically for any AEAD mode (a.k.a. nonce-based OAE).

As a contrast to that, perhaps we could find another word for the concept in this PR (i.e. #132) within the RustCrypto/AEAD implementations. Perhaps "incremental encryption"?

@tarcieri
Copy link
Member

tarcieri commented Sep 9, 2020

codecov.io check fails

Will fix, sorry about that.

Edit: #215 should hopefully address it.

@codecov-commenter
Copy link

codecov-commenter commented Sep 14, 2020

Codecov Report

Merging #214 into master will decrease coverage by 5.01%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #214      +/-   ##
==========================================
- Coverage   88.56%   83.55%   -5.02%     
==========================================
  Files          32       33       +1     
  Lines        1067     1131      +64     
==========================================
  Hits          945      945              
- Misses        122      186      +64     
Impacted Files Coverage Δ
eax/src/lib.rs 90.00% <ø> (ø)
eax/src/online.rs 0.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0d48b25...3b180b9. Read the comment docs.

@Xanewok
Copy link
Contributor Author

Xanewok commented Sep 14, 2020

Thanks for taking a look! I pushed a commit that prefers using the "online" word rather than stream.

I'm kind of torn about not implementing AeadMutInPlace directly. One of the reasons is that we shouldn't need to pass the nonce to the encrypt/decrypt function everytime, once you instantiate the EAX mode. Another one is that the chunk decryption will always perform tag calculation but that may be wasteful and might be hard for the optimizer to recognize. It looks like this interface may not be designed for streaming/online use?

Do you think I should also implement AeadMutInPlace for the newly-introduced EaxOnline?

@tarcieri
Copy link
Member

I pushed a commit that prefers using the "online" word rather than stream.

"Online" is also problematic, as STREAM (as in the Rogaway version) is a mode of Online Authenticated Encryption (specifically a nonce-based OAE or "nOAE").

@Xanewok
Copy link
Contributor Author

Xanewok commented Sep 14, 2020

As much as I understand reserving the "STREAM" name because it's introduced as a name/term for a useful generic framework capable of "online-ifying" a given nAE scheme, I don't think we should also reserve the "online" noun. After all, it's a well-known name of a property of an algorithm, just like EAX is online by design in general.

Hypothetically, if I were to find anything related to the OAE/CHAIN/STREAM framework, I'd expect to find it under "OAE{,1,2}" as a, for better or worse, yet another introduced term in the nomenclature of authenticated encryption.

@Xanewok
Copy link
Contributor Author

Xanewok commented Sep 14, 2020

Maybe "chunk(ed)" name would be better, then? Hopefully that would not imply the data to be of equal-length chunks, since "block" is a more commonly used name for this concept here.

@tarcieri
Copy link
Member

tarcieri commented Sep 14, 2020

Regardless of what name we choose, I think it might be worth designing a trait for this use case and adding it to https://github.com/RustCrypto/traits/tree/master/aead

/cc @newpavlov

(Note: that's not necessarily a blocker for this PR, but might be worth investigating before another release)

Copy link
Member

@newpavlov newpavlov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also not sure about a good name for such mode of operation. Maybe we could employ the IUF terminology here?

I think ideally we should design a trait for "online mode" first and update the crates later. There are some open design questions regarding buffering, enforcing encryptor/decryptor usage via type system and parallel processing of packets, but overall changes should be quite straightforward.

@Xanewok
Would you be willing to wait until such changes and use your fork in meantime? If you plan to use it in Sequoia in the near future, I guess we could merge this variant for now and push a minor release and migrate to the new traits in the next major release.

eax/src/online.rs Outdated Show resolved Hide resolved
@Xanewok
Copy link
Contributor Author

Xanewok commented Sep 14, 2020

Would you be willing to wait until such changes and use your fork in meantime? If you plan to use it in Sequoia in the near future, I guess we could merge this variant for now and push a minor release and migrate to the new traits in the next major release.

We currently use our own implementation but we decided that upstreaming the implementation would be a better idea and less frowned upon by the users AIUI. I believe that it'd be great for us to merge the approved version of this PR and use a newly-published minor release, as we'd like to ship our own 1.0 soon (cc @nwalfield @teythoon for release details)

There are some open design questions regarding buffering, enforcing encryptor/decryptor usage via type system and parallel processing of packets (...)

@newpavlov Do you have any concrete ideas that I could apply already to the API surface introduced here?

@newpavlov
Copy link
Member

newpavlov commented Sep 15, 2020

Do you have any concrete ideas that I could apply already to the API surface introduced here?

You already get it for free by using the ctr crate and CMAC can not be parallelized by design. The implementation could benefit from interleaving MAC update and application of the keystream (one-pass approach is cache-friendlier, than the currently used two-pass one, see #74), but it will not be trivial, since we do not want ctr to touch its inner buffer. Probably we will need deeper changes in our API to make such optimization more ergonomic, e.g. by exposing primitives which would do updates on blocks-only without any inner buffering, on top of which will be built buffering and "all or nothing" counterparts.

@nwalfield
Copy link

Would you be willing to wait until such changes and use your fork in meantime? If you plan to use it in Sequoia in the near future, I guess we could merge this variant for now and push a minor release and migrate to the new traits in the next major release.

Using a git fork is difficult, because as long as we are using a git fork, we can't make a release to crates.io, which, AIUI, only allows crates that rely on other crates published on crates.io.

We currently use our own implementation but we decided that upstreaming the implementation would be a better idea and less frowned upon by the users AIUI.

There are a couple of things going on here. First, we don't want to use our own crypto, even if it is only a few dozen lines of code. Second, if we rely on something else, it would be good that it not pull in too many dependencies. That is, if we use the eax crate to avoid including 50 lines of crypto code and eax pulls in x000 LOC, it's unclear that we've made the right tradeoff.

I believe that it'd be great for us to merge the approved version of this PR and use a newly-published minor release, as we'd like to ship our own 1.0 soon (cc @nwalfield @teythoon for release details)

We're getting very close to a 1.0 release. But, if we don't make it in the next few weeks, we'll almost certainly do another point release. So, we can't merge the eax code until the eax crate is released.

eax/src/online.rs Outdated Show resolved Hide resolved
@tarcieri
Copy link
Member

I'd be okay with merging this for now after DropBomb is removed and the unauthenticated decryption method is renamed to note it's hazmat and has an appropriately descriptive comment about how potential misuse could lead to catastrophic cryptographic failures.

tarcieri added a commit that referenced this pull request Sep 17, 2020
Releases versions that are upgraded to use `block-cipher` v0.8 and
`stream-cipher` v0.7.

- `aes-gcm` v0.7.0
- `aes-gcm-siv` v0.8.0
- `aes-siv` v0.4.0
- `ccm` v0.2.0
- `chacha20poly1305` v0.6.0
- `crypto_box` v0.4.0
- `eax` v0.2.0-pre (final release pending resolution of #214)
- `xsalsa20poly1305` v0.5.0
@tarcieri tarcieri mentioned this pull request Sep 17, 2020
tarcieri added a commit that referenced this pull request Sep 17, 2020
Releases versions that are upgraded to use `block-cipher` v0.8 and
`stream-cipher` v0.7.

- `aes-gcm` v0.7.0
- `aes-gcm-siv` v0.8.0
- `aes-siv` v0.4.0
- `ccm` v0.2.0
- `chacha20poly1305` v0.6.0
- `crypto_box` v0.4.0
- `eax` v0.2.0-pre (final release pending resolution of #214)
- `xsalsa20poly1305` v0.5.0
tarcieri added a commit that referenced this pull request Sep 17, 2020
Releases versions that are upgraded to use `block-cipher` v0.8 and
`stream-cipher` v0.7.

- `aes-gcm` v0.7.0
- `aes-gcm-siv` v0.8.0
- `aes-siv` v0.4.0
- `ccm` v0.2.0
- `chacha20poly1305` v0.6.0
- `crypto_box` v0.4.0
- `eax` v0.2.0-pre (final release pending resolution of #214)
- `xsalsa20poly1305` v0.5.0
tarcieri added a commit that referenced this pull request Sep 17, 2020
Releases versions that are upgraded to use `block-cipher` v0.8 and
`stream-cipher` v0.7.

- `aes-gcm` v0.7.0
- `aes-gcm-siv` v0.8.0
- `aes-siv` v0.4.0
- `ccm` v0.2.0
- `chacha20poly1305` v0.6.0
- `crypto_box` v0.4.0
- `eax` v0.2.0-pre (final release pending resolution of #214)
- `xsalsa20poly1305` v0.5.0
Brings back the old behavior - it's harder to misuse but separates the
implementations of online and offline variants.
@Xanewok
Copy link
Contributor Author

Xanewok commented Sep 17, 2020

Dropped the drop bomb code.

Before we merge this, I wanted to bring back the old behavior of first checking the tag and only then decrypting on success, in the offline variant.

This would, however, separate the offline/online implementations but I don't feel comfortable not testing the online variant at all. Unfortunately, the aead test case works in the integration tests format but I would not like to expose the raw set of operations and instead only expose the online mode to be used in either decrypt or encrypt mode. But because these are integration tests, I can't test private API nor I can doc(hidden) because of the trait interface I need to keep around a Key instance solely for tests...

Do you have any idea or preference on how to tackle this for the time being?

Should I adapt the aead::new_test! macro to accept a path to test case blob, rather than defaulting to data/$test_case.blb? This would allow me to define a test using that macro but from within the library unit tests, without exposing the internals.

eax/src/online.rs Outdated Show resolved Hide resolved
Comment on lines +254 to +256
// HACK: Needed for the test harness due to AEAD trait online/offline interface mismatch
#[cfg(test)]
key: Key<Cipher>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it'd really be good if we could figure out some other solution to this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is my one lingering concern but I don't consider it a showstopper

Copy link
Member

@tarcieri tarcieri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved, albeit with at least one notable open question: https://github.com/RustCrypto/AEADs/pull/214/files#r494580906

@tarcieri
Copy link
Member

@newpavlov WDYT?

Copy link
Member

@newpavlov newpavlov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good as a temporary solution, I think we can finalize the naming after adding streaming API to the aead crate.

@tarcieri
Can you do a release after merge?

@tarcieri tarcieri merged commit 0a4b0a9 into RustCrypto:master Sep 30, 2020
@tarcieri tarcieri mentioned this pull request Sep 30, 2020
@tarcieri
Copy link
Member

Released in v0.2.0

@Xanewok
Copy link
Contributor Author

Xanewok commented Sep 30, 2020

Thanks!

@Xanewok Xanewok deleted the eax-stream branch October 4, 2020 23:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants