proxygen
fizz::OpenSSLEVPCipher< EVPImpl > Class Template Reference

#include <OpenSSLEVPCipher.h>

Inheritance diagram for fizz::OpenSSLEVPCipher< EVPImpl >:
fizz::Aead

Public Member Functions

 OpenSSLEVPCipher ()
 
 ~OpenSSLEVPCipher () override=default
 
 OpenSSLEVPCipher (OpenSSLEVPCipher &&other)=default
 
OpenSSLEVPCipheroperator= (OpenSSLEVPCipher &&other)=default
 
void setKey (TrafficKey trafficKey) override
 
size_t keyLength () const override
 
size_t ivLength () const override
 
std::unique_ptr< folly::IOBufencrypt (std::unique_ptr< folly::IOBuf > &&plaintext, const folly::IOBuf *associatedData, uint64_t seqNum) const override
 
folly::Optional< std::unique_ptr< folly::IOBuf > > tryDecrypt (std::unique_ptr< folly::IOBuf > &&ciphertext, const folly::IOBuf *associatedData, uint64_t seqNum) const override
 
size_t getCipherOverhead () const override
 
void setEncryptedBufferHeadroom (size_t headroom) override
 
- Public Member Functions inherited from fizz::Aead
virtual ~Aead ()=default
 
virtual std::unique_ptr< folly::IOBufdecrypt (std::unique_ptr< folly::IOBuf > &&ciphertext, const folly::IOBuf *associatedData, uint64_t seqNum) const
 

Private Member Functions

std::array< uint8_t, EVPImpl::kIVLength > createIV (uint64_t seqNum) const
 

Private Attributes

TrafficKey trafficKey_
 
size_t headroom_ {5}
 
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_
 
folly::ssl::EvpCipherCtxUniquePtr decryptCtx_
 

Detailed Description

template<typename EVPImpl>
class fizz::OpenSSLEVPCipher< EVPImpl >

Aead implementation using an OpenSSL EvpCipher.

The template struct requires the following parameters:

  • Cipher: function returning EVP_CIPHER*
  • kKeyLength: length of key required
  • kIvLength: length of iv required
  • kTagLength: authentication tag length
  • kOperatesInBlocks: if the cipher outputs data in chunks vs. streaming 1:1 with the input
  • kRequiresPresetTagLen: if the cipher requires setting the tag length explicitly

Definition at line 39 of file OpenSSLEVPCipher.h.

Constructor & Destructor Documentation

template<typename EVPImpl >
fizz::OpenSSLEVPCipher< EVPImpl >::OpenSSLEVPCipher ( )

Definition at line 30 of file OpenSSLEVPCipher-inl.h.

30  {
31  encryptCtx_.reset(EVP_CIPHER_CTX_new());
32  if (encryptCtx_ == nullptr) {
33  throw std::runtime_error("Unable to allocate an EVP_CIPHER_CTX object");
34  }
35  decryptCtx_.reset(EVP_CIPHER_CTX_new());
36  if (decryptCtx_ == nullptr) {
37  throw std::runtime_error("Unable to allocate an EVP_CIPHER_CTX object");
38  }
39  if (EVP_EncryptInit_ex(
40  encryptCtx_.get(), EVPImpl::Cipher(), nullptr, nullptr, nullptr) !=
41  1) {
42  throw std::runtime_error("Init error");
43  }
44  if (EVP_CIPHER_CTX_ctrl(
45  encryptCtx_.get(),
46  EVP_CTRL_GCM_SET_IVLEN,
47  EVPImpl::kIVLength,
48  nullptr) != 1) {
49  throw std::runtime_error("Error setting iv length");
50  }
51  if (EVP_DecryptInit_ex(
52  decryptCtx_.get(), EVPImpl::Cipher(), nullptr, nullptr, nullptr) !=
53  1) {
54  throw std::runtime_error("Init error");
55  }
56  if (EVP_CIPHER_CTX_ctrl(
57  decryptCtx_.get(),
58  EVP_CTRL_GCM_SET_IVLEN,
59  EVPImpl::kIVLength,
60  nullptr) != 1) {
61  throw std::runtime_error("Error setting iv length");
62  }
63 
64  if (EVPImpl::kRequiresPresetTagLen) {
65  if (EVP_CIPHER_CTX_ctrl(
66  encryptCtx_.get(),
67  EVP_CTRL_GCM_SET_TAG,
68  EVPImpl::kTagLength,
69  nullptr) != 1) {
70  throw std::runtime_error("Error setting enc tag length");
71  }
72 
73  if (EVP_CIPHER_CTX_ctrl(
74  decryptCtx_.get(),
75  EVP_CTRL_GCM_SET_TAG,
76  EVPImpl::kTagLength,
77  nullptr) != 1) {
78  throw std::runtime_error("Error setting dec tag length");
79  }
80  }
81 }
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_
folly::ssl::EvpCipherCtxUniquePtr decryptCtx_
template<typename EVPImpl >
fizz::OpenSSLEVPCipher< EVPImpl >::~OpenSSLEVPCipher ( )
overridedefault
template<typename EVPImpl >
fizz::OpenSSLEVPCipher< EVPImpl >::OpenSSLEVPCipher ( OpenSSLEVPCipher< EVPImpl > &&  other)
default

Member Function Documentation

template<typename EVPImpl >
std::array< uint8_t, EVPImpl::kIVLength > fizz::OpenSSLEVPCipher< EVPImpl >::createIV ( uint64_t  seqNum) const
private

Definition at line 153 of file OpenSSLEVPCipher-inl.h.

References folly::Endian::big(), folly::range(), uint64_t, and fizz::XOR().

Referenced by fizz::OpenSSLEVPCipher< EVPImpl >::setEncryptedBufferHeadroom().

154  {
155  std::array<uint8_t, EVPImpl::kIVLength> iv;
156  uint64_t bigEndianSeqNum = folly::Endian::big(seqNum);
157  const size_t prefixLength = EVPImpl::kIVLength - sizeof(uint64_t);
158  memset(iv.data(), 0, prefixLength);
159  memcpy(iv.data() + prefixLength, &bigEndianSeqNum, 8);
160  XOR(trafficKey_.iv->coalesce(), folly::range(iv));
161  return iv;
162 }
std::unique_ptr< folly::IOBuf > iv
Definition: Aead.h:18
void XOR(ByteRange first, MutableByteRange second)
Definition: IOBufUtil.cpp:33
static T big(T x)
Definition: Bits.h:259
constexpr Range< Iter > range(Iter first, Iter last)
Definition: Range.h:1114
template<typename EVPImpl >
std::unique_ptr< folly::IOBuf > fizz::OpenSSLEVPCipher< EVPImpl >::encrypt ( std::unique_ptr< folly::IOBuf > &&  plaintext,
const folly::IOBuf associatedData,
uint64_t  seqNum 
) const
overridevirtual

Encrypts plaintext. Will throw on error.

Implements fizz::Aead.

Definition at line 113 of file OpenSSLEVPCipher-inl.h.

References fizz::detail::evpEncrypt(), and folly::gen::move.

Referenced by fizz::OpenSSLEVPCipher< EVPImpl >::ivLength().

116  {
117  auto iv = createIV(seqNum);
118  return detail::evpEncrypt(
119  std::move(plaintext),
120  associatedData,
121  iv,
122  EVPImpl::kTagLength,
123  EVPImpl::kOperatesInBlocks,
124  headroom_,
125  encryptCtx_.get());
126 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_
std::array< uint8_t, EVPImpl::kIVLength > createIV(uint64_t seqNum) const
std::unique_ptr< folly::IOBuf > evpEncrypt(std::unique_ptr< folly::IOBuf > &&plaintext, const folly::IOBuf *associatedData, folly::ByteRange iv, size_t tagLen, bool useBlockOps, size_t headroom, EVP_CIPHER_CTX *encryptCtx)
template<typename EVPImpl >
size_t fizz::OpenSSLEVPCipher< EVPImpl >::getCipherOverhead ( ) const
overridevirtual

Returns the number of bytes the aead will add to the plaintext (size of ciphertext - size of plaintext).

Implements fizz::Aead.

Definition at line 148 of file OpenSSLEVPCipher-inl.h.

Referenced by fizz::OpenSSLEVPCipher< EVPImpl >::ivLength().

148  {
149  return EVPImpl::kTagLength;
150 }
template<typename EVPImpl >
size_t fizz::OpenSSLEVPCipher< EVPImpl >::ivLength ( ) const
inlineoverridevirtual

Returns the number of iv bytes needed by this aead.

Implements fizz::Aead.

Definition at line 55 of file OpenSSLEVPCipher.h.

References fizz::OpenSSLEVPCipher< EVPImpl >::encrypt(), fizz::OpenSSLEVPCipher< EVPImpl >::getCipherOverhead(), fizz::OpenSSLEVPCipher< EVPImpl >::tryDecrypt(), and uint64_t.

55  {
56  return EVPImpl::kIVLength;
57  }
template<typename EVPImpl >
size_t fizz::OpenSSLEVPCipher< EVPImpl >::keyLength ( ) const
inlineoverridevirtual

Returns the number of key bytes needed by this aead.

Implements fizz::Aead.

Definition at line 51 of file OpenSSLEVPCipher.h.

51  {
52  return EVPImpl::kKeyLength;
53  }
template<typename EVPImpl >
OpenSSLEVPCipher& fizz::OpenSSLEVPCipher< EVPImpl >::operator= ( OpenSSLEVPCipher< EVPImpl > &&  other)
default
template<typename EVPImpl >
void fizz::OpenSSLEVPCipher< EVPImpl >::setEncryptedBufferHeadroom ( size_t  headroom)
inlineoverridevirtual

Set a hint to the AEAD about how much space to try to leave as headroom for ciphertexts returned from encrypt. Implementations may or may not honor this.

Implements fizz::Aead.

Definition at line 75 of file OpenSSLEVPCipher.h.

References fizz::OpenSSLEVPCipher< EVPImpl >::createIV(), fizz::OpenSSLEVPCipher< EVPImpl >::headroom_, and uint64_t.

75  {
76  headroom_ = headroom;
77  }
template<typename EVPImpl >
void fizz::OpenSSLEVPCipher< EVPImpl >::setKey ( TrafficKey  key)
overridevirtual

Sets the key and iv for this aead. The length of the key and iv must match keyLength() and ivLength().

Implements fizz::Aead.

Definition at line 84 of file OpenSSLEVPCipher-inl.h.

References fizz::TrafficKey::iv, fizz::TrafficKey::key, and folly::gen::move.

84  {
85  trafficKey.key->coalesce();
86  trafficKey.iv->coalesce();
87  if (trafficKey.key->length() != EVPImpl::kKeyLength) {
88  throw std::runtime_error("Invalid key");
89  }
90  if (trafficKey.iv->length() != EVPImpl::kIVLength) {
91  throw std::runtime_error("Invalid IV");
92  }
93  trafficKey_ = std::move(trafficKey);
94  if (EVP_EncryptInit_ex(
95  encryptCtx_.get(),
96  nullptr,
97  nullptr,
98  trafficKey_.key->data(),
99  nullptr) != 1) {
100  throw std::runtime_error("Error setting encrypt key");
101  }
102  if (EVP_DecryptInit_ex(
103  decryptCtx_.get(),
104  nullptr,
105  nullptr,
106  trafficKey_.key->data(),
107  nullptr) != 1) {
108  throw std::runtime_error("Error setting decrypt key");
109  }
110 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::unique_ptr< folly::IOBuf > key
Definition: Aead.h:17
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_
folly::ssl::EvpCipherCtxUniquePtr decryptCtx_
template<typename EVPImpl >
folly::Optional< std::unique_ptr< folly::IOBuf > > fizz::OpenSSLEVPCipher< EVPImpl >::tryDecrypt ( std::unique_ptr< folly::IOBuf > &&  ciphertext,
const folly::IOBuf associatedData,
uint64_t  seqNum 
) const
overridevirtual

Decrypt ciphertext. Will return none if the ciphertext does not decrypt successfully. May still throw from errors unrelated to ciphertext.

Implements fizz::Aead.

Definition at line 130 of file OpenSSLEVPCipher-inl.h.

References fizz::detail::evpDecrypt(), and folly::gen::move.

Referenced by fizz::OpenSSLEVPCipher< EVPImpl >::ivLength().

133  {
134  auto iv = createIV(seqNum);
135  // buffer to copy the tag into when we decrypt
136  std::array<uint8_t, EVPImpl::kTagLength> tagData;
137  folly::MutableByteRange tagOut{tagData};
138  return detail::evpDecrypt(
139  std::move(ciphertext),
140  associatedData,
141  iv,
142  tagOut,
143  EVPImpl::kOperatesInBlocks,
144  decryptCtx_.get());
145 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::ssl::EvpCipherCtxUniquePtr decryptCtx_
std::array< uint8_t, EVPImpl::kIVLength > createIV(uint64_t seqNum) const
folly::Optional< std::unique_ptr< folly::IOBuf > > evpDecrypt(std::unique_ptr< folly::IOBuf > &&ciphertext, const folly::IOBuf *associatedData, folly::ByteRange iv, folly::MutableByteRange tag, bool useBlockOps, EVP_CIPHER_CTX *decryptCtx)

Member Data Documentation

template<typename EVPImpl >
folly::ssl::EvpCipherCtxUniquePtr fizz::OpenSSLEVPCipher< EVPImpl >::decryptCtx_
private

Definition at line 86 of file OpenSSLEVPCipher.h.

template<typename EVPImpl >
folly::ssl::EvpCipherCtxUniquePtr fizz::OpenSSLEVPCipher< EVPImpl >::encryptCtx_
private

Definition at line 85 of file OpenSSLEVPCipher.h.

template<typename EVPImpl >
size_t fizz::OpenSSLEVPCipher< EVPImpl >::headroom_ {5}
private
template<typename EVPImpl >
TrafficKey fizz::OpenSSLEVPCipher< EVPImpl >::trafficKey_
private

Definition at line 82 of file OpenSSLEVPCipher.h.


The documentation for this class was generated from the following files: