Skip to content

Commit

Permalink
Expand Aead::decrypt() to accept explicit nonce
Browse files Browse the repository at this point in the history
Summary: To allow for aead decryption outside of tls add version of Aead::decrypt() that accepts an explicitely defined nonce.

Reviewed By: mingtaoy

Differential Revision: D37632330

fbshipit-source-id: b0fd9d8f5f0014baac5ebed811a26416687c78c0
  • Loading branch information
NickR23 authored and facebook-github-bot committed Jul 6, 2022
1 parent a2972cc commit 7baf5ce
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 3 deletions.
66 changes: 66 additions & 0 deletions fizz/crypto/aead/Aead.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,28 @@ class Aead {
{BufferOption::RespectSharedPolicy, AllocationOption::Allow});
}

/**
* Decrypt ciphertext. Will throw if the ciphertext does not decrypt
* successfully.
*
* This version of decrypt uses a nonce passed in explicitly
* by the caller; consequently, this interface can be used
* to perform AEAD outside of a TLS specific application.
*
* Uses BufferOption::RespectSharedPolicy and AllocationOption::Allow by
* default.
*/
std::unique_ptr<folly::IOBuf> decrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce) const {
return decrypt(
std::move(ciphertext),
associatedData,
nonce,
{BufferOption::RespectSharedPolicy, AllocationOption::Allow});
}

virtual std::unique_ptr<folly::IOBuf> decrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
Expand All @@ -182,6 +204,22 @@ class Aead {
return std::move(*plaintext);
}

virtual std::unique_ptr<folly::IOBuf> decrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
AeadOptions options) const {
auto plaintext = tryDecrypt(
std::forward<std::unique_ptr<folly::IOBuf>>(ciphertext),
associatedData,
nonce,
options);
if (!plaintext) {
throw std::runtime_error("decryption failed");
}
return std::move(*plaintext);
}

/**
* Decrypt ciphertext. Will return none if the ciphertext does not decrypt
* successfully. May still throw from errors unrelated to ciphertext.
Expand All @@ -200,12 +238,40 @@ class Aead {
{BufferOption::RespectSharedPolicy, AllocationOption::Allow});
}

/**
* Decrypt ciphertext. Will return none if the ciphertext does not decrypt
* successfully. May still throw from errors unrelated to ciphertext.
*
* This version of tryDecrypt uses a nonce passed in explicitly
* by the caller; consequently, this interface can be used
* to perform AEAD outside of a TLS specific application.
*
* Uses BufferOption::RespectSharedPolicy and AllocationOption::Allow by
* default.
*/
folly::Optional<std::unique_ptr<folly::IOBuf>> tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce) const {
return tryDecrypt(
std::forward<std::unique_ptr<folly::IOBuf>>(ciphertext),
associatedData,
nonce,
{BufferOption::RespectSharedPolicy, AllocationOption::Allow});
}

virtual folly::Optional<std::unique_ptr<folly::IOBuf>> tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
uint64_t seqNum,
AeadOptions options) const = 0;

virtual folly::Optional<std::unique_ptr<folly::IOBuf>> tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
AeadOptions options) const = 0;

/**
* Returns the number of bytes the aead will add to the plaintext (size of
* ciphertext - size of plaintext).
Expand Down
18 changes: 15 additions & 3 deletions fizz/crypto/aead/OpenSSLEVPCipher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,12 +481,24 @@ folly::Optional<std::unique_ptr<folly::IOBuf>> OpenSSLEVPCipher::tryDecrypt(
const folly::IOBuf* associatedData,
uint64_t seqNum,
Aead::AeadOptions options) const {
auto iv = createIV(seqNum);
return tryDecrypt(
std::move(ciphertext),
associatedData,
folly::ByteRange(iv.data(), ivLength_),
options);
}

folly::Optional<std::unique_ptr<folly::IOBuf>> OpenSSLEVPCipher::tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
Aead::AeadOptions options) const {
// Check that there's enough data to decrypt
if (tagLength_ > ciphertext->computeChainDataLength()) {
return folly::none;
}

auto iv = createIV(seqNum);
auto inPlace =
(!ciphertext->isShared() ||
options.bufferOpt != Aead::BufferOption::RespectSharedPolicy);
Expand All @@ -508,7 +520,7 @@ folly::Optional<std::unique_ptr<folly::IOBuf>> OpenSSLEVPCipher::tryDecrypt(
return evpDecrypt(
std::move(ciphertext),
associatedData,
folly::ByteRange(iv.data(), ivLength_),
nonce,
tagOut,
operatesInBlocks_,
decryptCtx_.get(),
Expand All @@ -526,7 +538,7 @@ folly::Optional<std::unique_ptr<folly::IOBuf>> OpenSSLEVPCipher::tryDecrypt(
return evpDecrypt(
std::move(ciphertext),
associatedData,
folly::ByteRange(iv.data(), ivLength_),
nonce,
tagOut,
operatesInBlocks_,
decryptCtx_.get(),
Expand Down
6 changes: 6 additions & 0 deletions fizz/crypto/aead/OpenSSLEVPCipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ class OpenSSLEVPCipher : public Aead {
uint64_t seqNum,
Aead::AeadOptions options) const override;

folly::Optional<std::unique_ptr<folly::IOBuf>> tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
Aead::AeadOptions options) const override;

size_t getCipherOverhead() const override;

void setEncryptedBufferHeadroom(size_t headroom) override {
Expand Down
16 changes: 16 additions & 0 deletions fizz/crypto/aead/test/Mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ class MockAead : public Aead {
return _tryDecrypt(ciphertext, associatedData, seqNum, options);
}

MOCK_METHOD(
folly::Optional<std::unique_ptr<folly::IOBuf>>,
_tryDecryptNonce,
(std::unique_ptr<folly::IOBuf> & ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
Aead::AeadOptions options),
(const));
folly::Optional<std::unique_ptr<folly::IOBuf>> tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
Aead::AeadOptions options) const override {
return _tryDecryptNonce(ciphertext, associatedData, nonce, options);
}

MOCK_METHOD(folly::Optional<TrafficKey>, getKey, (), (const));

void setDefaults() {
Expand Down
18 changes: 18 additions & 0 deletions fizz/crypto/hpke/test/Mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ class MockAeadCipher : public Aead {
std::move(ciphertext), associatedData, seqNum, options);
}

std::unique_ptr<folly::IOBuf> decrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
AeadOptions options) const override {
return actualCipher_->decrypt(
std::move(ciphertext), associatedData, nonce, options);
}

folly::Optional<std::unique_ptr<folly::IOBuf>> tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
Expand All @@ -85,6 +94,15 @@ class MockAeadCipher : public Aead {
std::move(ciphertext), associatedData, seqNum, options);
}

folly::Optional<std::unique_ptr<folly::IOBuf>> tryDecrypt(
std::unique_ptr<folly::IOBuf>&& ciphertext,
const folly::IOBuf* associatedData,
folly::ByteRange nonce,
AeadOptions options) const override {
return actualCipher_->tryDecrypt(
std::move(ciphertext), associatedData, nonce, options);
}

size_t getCipherOverhead() const override {
return actualCipher_->getCipherOverhead();
}
Expand Down

0 comments on commit 7baf5ce

Please sign in to comment.