Botan 3.13.0
Crypto and TLS for C&
gcm_siv.h
Go to the documentation of this file.
1/*
2* GCM-SIV Mode
3* (C) 2026 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_AEAD_GCM_SIV_H_
9#define BOTAN_AEAD_GCM_SIV_H_
10
11#include <botan/aead.h>
12
13#include <botan/block_cipher.h>
14#include <botan/internal/polyval.h>
15
16namespace Botan {
17
18/**
19* GCM-SIV Mode (RFC 8452)
20*/
21class GCM_SIV_Mode : public AEAD_Mode /* NOLINT(*-special-member-functions) */ {
22 public:
23 void set_associated_data_n(size_t idx, std::span<const uint8_t> ad) final;
24
25 std::string name() const final;
26
27 size_t update_granularity() const final;
28
29 size_t ideal_granularity() const final;
30
32
33 bool valid_nonce_length(size_t len) const final;
34
35 size_t tag_size() const final { return 16; }
36
37 bool requires_entire_message() const final { return true; }
38
39 /// The AD is buffered as-is; it is not processed until finish
40 bool associated_data_requires_key() const final { return false; }
41
42 void clear() final;
43
44 void reset() final;
45
46 std::string provider() const final;
47
48 bool has_keying_material() const final;
49
50 ~GCM_SIV_Mode() override;
51
52 protected:
53 explicit GCM_SIV_Mode(std::unique_ptr<BlockCipher> cipher);
54
55 static constexpr size_t BS = 16;
56
57 /// RFC 8452 limits both the plaintext and the AD to 2**36 bytes
58 static constexpr uint64_t MAX_INPUT_LEN = static_cast<uint64_t>(1) << 36;
59
60 secure_vector<uint8_t>& msg_buf() { return m_msg_buf; }
61
62 bool in_msg() const { return m_in_msg; }
63
64 /// Compute the expected tag for the (unpadded) plaintext
65 std::array<uint8_t, BS> compute_tag(std::span<const uint8_t> ptext);
66
67 /// XOR the buffer with the CTR keystream, starting from the tag-derived counter
68 void ctr_xor(std::span<const uint8_t, BS> tag, uint8_t buf[], size_t len);
69
70 private:
71 void start_msg(const uint8_t nonce[], size_t nonce_len) final;
72 size_t process_msg(uint8_t buf[], size_t size) final;
73
74 void key_schedule(std::span<const uint8_t> key) final;
75
76 const std::string m_cipher_name;
77 const Key_Length_Specification m_key_spec;
78
79 std::unique_ptr<BlockCipher> m_cipher; // keyed with the key-generating key
80 std::unique_ptr<BlockCipher> m_msg_cipher; // keyed with the per-message encryption key
81 Polyval m_polyval;
82
83 size_t m_kgk_len = 0;
84 std::array<uint8_t, 12> m_nonce{};
86 secure_vector<uint8_t> m_msg_buf;
87 bool m_in_msg = false;
88};
89
90/**
91* GCM-SIV Encryption
92*/
93class GCM_SIV_Encryption final : public GCM_SIV_Mode {
94 public:
95 /**
96 * @param cipher the 128 bit block cipher to use
97 */
98 explicit GCM_SIV_Encryption(std::unique_ptr<BlockCipher> cipher) : GCM_SIV_Mode(std::move(cipher)) {}
99
100 size_t output_length(size_t input_length) const override;
101
102 size_t minimum_final_size() const override { return 0; }
103
104 private:
105 void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
106};
107
108/**
109* GCM-SIV Decryption
110*/
111class GCM_SIV_Decryption final : public GCM_SIV_Mode {
112 public:
113 /**
114 * @param cipher the 128 bit block cipher to use
115 */
116 explicit GCM_SIV_Decryption(std::unique_ptr<BlockCipher> cipher) : GCM_SIV_Mode(std::move(cipher)) {}
117
118 size_t output_length(size_t input_length) const override;
119
120 size_t minimum_final_size() const override { return tag_size(); }
121
122 private:
123 void finish_msg(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
124};
125
126} // namespace Botan
127
128#endif
size_t output_length(size_t input_length) const override
Definition gcm_siv.cpp:249
size_t minimum_final_size() const override
Definition gcm_siv.h:120
GCM_SIV_Decryption(std::unique_ptr< BlockCipher > cipher)
Definition gcm_siv.h:116
size_t minimum_final_size() const override
Definition gcm_siv.h:102
size_t output_length(size_t input_length) const override
Definition gcm_siv.cpp:227
GCM_SIV_Encryption(std::unique_ptr< BlockCipher > cipher)
Definition gcm_siv.h:98
std::string name() const final
Definition gcm_siv.cpp:68
static constexpr size_t BS
Definition gcm_siv.h:55
static constexpr uint64_t MAX_INPUT_LEN
RFC 8452 limits both the plaintext and the AD to 2**36 bytes.
Definition gcm_siv.h:58
bool valid_nonce_length(size_t len) const final
Definition gcm_siv.cpp:84
bool in_msg() const
Definition gcm_siv.h:62
std::string provider() const final
Definition gcm_siv.cpp:72
size_t ideal_granularity() const final
Definition gcm_siv.cpp:80
void ctr_xor(std::span< const uint8_t, BS > tag, uint8_t buf[], size_t len)
XOR the buffer with the CTR keystream, starting from the tag-derived counter.
Definition gcm_siv.cpp:194
void clear() final
Definition gcm_siv.cpp:52
size_t tag_size() const final
Definition gcm_siv.h:35
Key_Length_Specification key_spec() const final
Definition gcm_siv.cpp:88
bool has_keying_material() const final
Definition gcm_siv.cpp:92
void reset() final
Definition gcm_siv.cpp:59
bool associated_data_requires_key() const final
The AD is buffered as-is; it is not processed until finish.
Definition gcm_siv.h:40
secure_vector< uint8_t > & msg_buf()
Definition gcm_siv.h:60
bool requires_entire_message() const final
Definition gcm_siv.h:37
size_t update_granularity() const final
Definition gcm_siv.cpp:76
void set_associated_data_n(size_t idx, std::span< const uint8_t > ad) final
Definition gcm_siv.cpp:102
GCM_SIV_Mode(std::unique_ptr< BlockCipher > cipher)
Definition gcm_siv.cpp:44
std::array< uint8_t, BS > compute_tag(std::span< const uint8_t > ptext)
Compute the expected tag for the (unpadded) plaintext.
Definition gcm_siv.cpp:169
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128