|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#ifdef OPENSSL_IS_BORINGSSL |
| 4 | + |
| 5 | +class Aead final : public ModeMixin<Aead> { |
| 6 | + private: |
| 7 | + // BoringSSL does not keep a list of AEADs, so we need to maintain our own. |
| 8 | + struct AeadInfo { |
| 9 | + std::string name; |
| 10 | + int mode; |
| 11 | + int nid = 0; // Note: BoringSSL only defines NIDs for some AEADs |
| 12 | + }; |
| 13 | + |
| 14 | + public: |
| 15 | + Aead() = default; |
| 16 | + Aead(const AeadInfo* info, const EVP_AEAD* aead) : info_(info), aead_(aead) {} |
| 17 | + Aead(const Aead&) = default; |
| 18 | + Aead& operator=(const Aead&) = default; |
| 19 | + NCRYPTO_DISALLOW_MOVE(Aead) |
| 20 | + |
| 21 | + inline const EVP_AEAD* get() const { return aead_; } |
| 22 | + inline operator const EVP_AEAD*() const { return aead_; } |
| 23 | + inline operator bool() const { return aead_ != nullptr; } |
| 24 | + |
| 25 | + int getMode() const; |
| 26 | + int getNonceLength() const; |
| 27 | + int getKeyLength() const; |
| 28 | + int getBlockSize() const; |
| 29 | + int getMaxOverhead() const; |
| 30 | + int getMaxTagLength() const; |
| 31 | + std::string_view getName() const; |
| 32 | + |
| 33 | + static const Aead FromName(std::string_view name); |
| 34 | + |
| 35 | + // TODO(npaun): BoringSSL does not define NIDs for all AEADs. |
| 36 | + // This method is included only for implementing getCipherInfo and can't be |
| 37 | + // used to construct an Aead instance. |
| 38 | + int getNid() const; |
| 39 | + // static const AEAD FromNid(int nid); |
| 40 | + |
| 41 | + static const Aead FromCtx(std::string_view name, const AeadCtxPointer& ctx); |
| 42 | + |
| 43 | + using AeadNameCallback = std::function<void(std::string_view name)>; |
| 44 | + |
| 45 | + // Iterates the known ciphers if the underlying implementation |
| 46 | + // is able to do so. |
| 47 | + static void ForEach(AeadNameCallback callback); |
| 48 | + |
| 49 | + // Utilities to get various AEADs by type. |
| 50 | + |
| 51 | + static const Aead EMPTY; |
| 52 | + static const Aead AES_128_GCM; |
| 53 | + static const Aead AES_192_GCM; |
| 54 | + static const Aead AES_256_GCM; |
| 55 | + static const Aead CHACHA20_POLY1305; |
| 56 | + static const Aead XCHACHA20_POLY1305; |
| 57 | + static const Aead AES_128_CTR_HMAC_SHA256; |
| 58 | + static const Aead AES_256_CTR_HMAC_SHA256; |
| 59 | + static const Aead AES_128_GCM_SIV; |
| 60 | + static const Aead AES_256_GCM_SIV; |
| 61 | + static const Aead AES_128_GCM_RANDNONCE; |
| 62 | + static const Aead AES_256_GCM_RANDNONCE; |
| 63 | + static const Aead AES_128_CCM_BLUETOOTH; |
| 64 | + static const Aead AES_128_CCM_BLUETOOTH_8; |
| 65 | + static const Aead AES_128_CCM_MATTER; |
| 66 | + static const Aead AES_128_EAX; |
| 67 | + static const Aead AES_256_EAX; |
| 68 | + |
| 69 | + private: |
| 70 | + const EVP_AEAD* aead_ = nullptr; |
| 71 | + const AeadInfo* info_ = nullptr; |
| 72 | + |
| 73 | + using AeadConstructor = const EVP_AEAD* (*)(); |
| 74 | + static const std::unordered_map<AeadConstructor, AeadInfo> aeadIndex; |
| 75 | + static const Aead FromConstructor(AeadConstructor construct); |
| 76 | +}; |
| 77 | + |
| 78 | +class AeadCtxPointer final { |
| 79 | + public: |
| 80 | + static AeadCtxPointer New( |
| 81 | + const Aead& aead, |
| 82 | + bool encrypt, |
| 83 | + const unsigned char* key = nullptr, |
| 84 | + size_t keyLen = 0, |
| 85 | + size_t tagLen = EVP_AEAD_DEFAULT_TAG_LENGTH /* = 0 */); |
| 86 | + |
| 87 | + AeadCtxPointer() = default; |
| 88 | + explicit AeadCtxPointer(EVP_AEAD_CTX* ctx); |
| 89 | + AeadCtxPointer(AeadCtxPointer&& other) noexcept; |
| 90 | + AeadCtxPointer& operator=(AeadCtxPointer&& other) noexcept; |
| 91 | + NCRYPTO_DISALLOW_COPY(AeadCtxPointer) |
| 92 | + ~AeadCtxPointer(); |
| 93 | + |
| 94 | + inline bool operator==(std::nullptr_t) const noexcept { |
| 95 | + return ctx_ == nullptr; |
| 96 | + } |
| 97 | + inline operator bool() const { return ctx_ != nullptr; } |
| 98 | + inline EVP_AEAD_CTX* get() const { return ctx_.get(); } |
| 99 | + inline operator EVP_AEAD_CTX*() const { return ctx_.get(); } |
| 100 | + void reset(EVP_AEAD_CTX* ctx = nullptr); |
| 101 | + EVP_AEAD_CTX* release(); |
| 102 | + |
| 103 | + bool init(const Aead& aead, |
| 104 | + bool encrypt, |
| 105 | + const unsigned char* key = nullptr, |
| 106 | + size_t keyLen = 0, |
| 107 | + size_t tagLen = EVP_AEAD_DEFAULT_TAG_LENGTH /* = 0 */); |
| 108 | + |
| 109 | + // TODO(npaun): BoringSSL does not define NIDs for all AEADs. |
| 110 | + // Decide if we will even implement this method. |
| 111 | + // int getNid() const; |
| 112 | + |
| 113 | + bool encrypt(const Buffer<const unsigned char>& in, |
| 114 | + Buffer<unsigned char>& out, |
| 115 | + Buffer<unsigned char>& tag, |
| 116 | + const Buffer<const unsigned char>& nonce, |
| 117 | + const Buffer<const unsigned char>& aad); |
| 118 | + |
| 119 | + bool decrypt(const Buffer<const unsigned char>& in, |
| 120 | + Buffer<unsigned char>& out, |
| 121 | + const Buffer<const unsigned char>& tag, |
| 122 | + const Buffer<const unsigned char>& nonce, |
| 123 | + const Buffer<const unsigned char>& aad); |
| 124 | + |
| 125 | + private: |
| 126 | + DeleteFnPtr<EVP_AEAD_CTX, EVP_AEAD_CTX_free> ctx_; |
| 127 | +}; |
| 128 | + |
| 129 | +#endif // OPENSSL_IS_BORINGSSL |
0 commit comments