Botan 2.19.5 Crypto and TLS for C&

chacha20poly1305.cpp
Go to the documentation of this file.
1/*
2* ChaCha20Poly1305 AEAD
3* (C) 2014,2016,2018 Jack Lloyd
4* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/chacha20poly1305.h>
10#include <botan/loadstor.h>
11
12 namespace Botan {
13
14 ChaCha20Poly1305_Mode::ChaCha20Poly1305_Mode() :
15 m_chacha(StreamCipher::create("ChaCha")),
16 m_poly1305(MessageAuthenticationCode::create("Poly1305"))
17 {
18 if(!m_chacha || !m_poly1305)
19 throw Algorithm_Not_Found("ChaCha20Poly1305");
20 }
21
22 bool ChaCha20Poly1305_Mode::valid_nonce_length(size_t n) const
23 {
24 return (n == 8 || n == 12 || n == 24);
25 }
26
27 void ChaCha20Poly1305_Mode::clear()
28 {
29 m_chacha->clear();
30 m_poly1305->clear();
31 reset();
32 }
33
34 void ChaCha20Poly1305_Mode::reset()
35 {
36 m_ad.clear();
37 m_ctext_len = 0;
38 m_nonce_len = 0;
39 }
40
41 void ChaCha20Poly1305_Mode::key_schedule(const uint8_t key[], size_t length)
42 {
43 m_chacha->set_key(key, length);
44 }
45
46 void ChaCha20Poly1305_Mode::set_associated_data(const uint8_t ad[], size_t length)
47 {
48 if(m_ctext_len > 0 || m_nonce_len > 0)
49 throw Invalid_State("Cannot set AD for ChaCha20Poly1305 while processing a message");
50 m_ad.assign(ad, ad + length);
51 }
52
53 void ChaCha20Poly1305_Mode::update_len(size_t len)
54 {
55 uint8_t len8[8] = { 0 };
56 store_le(static_cast<uint64_t>(len), len8);
57 m_poly1305->update(len8, 8);
58 }
59
60 void ChaCha20Poly1305_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
61 {
62 if(!valid_nonce_length(nonce_len))
63 throw Invalid_IV_Length(name(), nonce_len);
64
65 m_ctext_len = 0;
66 m_nonce_len = nonce_len;
67
68 m_chacha->set_iv(nonce, nonce_len);
69
70 uint8_t first_block[64];
71 m_chacha->write_keystream(first_block, sizeof(first_block));
72
73 m_poly1305->set_key(first_block, 32);
74 // Remainder of first block is discarded
75 secure_scrub_memory(first_block, sizeof(first_block));
76
77 m_poly1305->update(m_ad);
78
79 if(cfrg_version())
80 {
81 if(m_ad.size() % 16)
82 {
83 const uint8_t zeros[16] = { 0 };
84 m_poly1305->update(zeros, 16 - m_ad.size() % 16);
85 }
86 }
87 else
88 {
89 update_len(m_ad.size());
90 }
91 }
92
93 size_t ChaCha20Poly1305_Encryption::process(uint8_t buf[], size_t sz)
94 {
95 m_chacha->cipher1(buf, sz);
96 m_poly1305->update(buf, sz); // poly1305 of ciphertext
97 m_ctext_len += sz;
98 return sz;
99 }
100
101 void ChaCha20Poly1305_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
102 {
103 update(buffer, offset);
104 if(cfrg_version())
105 {
106 if(m_ctext_len % 16)
107 {
108 const uint8_t zeros[16] = { 0 };
109 m_poly1305->update(zeros, 16 - m_ctext_len % 16);
110 }
111 update_len(m_ad.size());
112 }
113 update_len(m_ctext_len);
114
115 buffer.resize(buffer.size() + tag_size());
116 m_poly1305->final(&buffer[buffer.size() - tag_size()]);
117 m_ctext_len = 0;
118 m_nonce_len = 0;
119 }
120
121 size_t ChaCha20Poly1305_Decryption::process(uint8_t buf[], size_t sz)
122 {
123 m_poly1305->update(buf, sz); // poly1305 of ciphertext
124 m_chacha->cipher1(buf, sz);
125 m_ctext_len += sz;
126 return sz;
127 }
128
129 void ChaCha20Poly1305_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
130 {
131 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
132 const size_t sz = buffer.size() - offset;
133 uint8_t* buf = buffer.data() + offset;
134
135 BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input");
136
137 const size_t remaining = sz - tag_size();
138
139 if(remaining)
140 {
141 m_poly1305->update(buf, remaining); // poly1305 of ciphertext
142 m_chacha->cipher1(buf, remaining);
143 m_ctext_len += remaining;
144 }
145
146 if(cfrg_version())
147 {
148 if(m_ctext_len % 16)
149 {
150 const uint8_t zeros[16] = { 0 };
151 m_poly1305->update(zeros, 16 - m_ctext_len % 16);
152 }
153 update_len(m_ad.size());
154 }
155
156 update_len(m_ctext_len);
157
158 uint8_t mac[16];
159 m_poly1305->final(mac);
160
161 const uint8_t* included_tag = &buf[remaining];
162
163 m_ctext_len = 0;
164 m_nonce_len = 0;
165
166 if(!constant_time_compare(mac, included_tag, tag_size()))
167 throw Invalid_Authentication_Tag("ChaCha20Poly1305 tag check failed");
168 buffer.resize(offset + remaining);
169 }
170
171}
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::Algorithm_Not_Found
Definition: exceptn.h:266
Botan::ChaCha20Poly1305_Decryption::process
size_t process(uint8_t buf[], size_t size) override
Definition: chacha20poly1305.cpp:121
Botan::ChaCha20Poly1305_Decryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: chacha20poly1305.cpp:129
Botan::ChaCha20Poly1305_Encryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: chacha20poly1305.cpp:101
Botan::ChaCha20Poly1305_Encryption::process
size_t process(uint8_t buf[], size_t size) override
Definition: chacha20poly1305.cpp:93
Botan::ChaCha20Poly1305_Mode::m_ctext_len
size_t m_ctext_len
Definition: chacha20poly1305.h:57
Botan::ChaCha20Poly1305_Mode::valid_nonce_length
bool valid_nonce_length(size_t n) const override
Definition: chacha20poly1305.cpp:22
Botan::ChaCha20Poly1305_Mode::m_ad
secure_vector< uint8_t > m_ad
Definition: chacha20poly1305.h:55
Botan::ChaCha20Poly1305_Mode::ChaCha20Poly1305_Mode
ChaCha20Poly1305_Mode()
Definition: chacha20poly1305.cpp:14
Botan::ChaCha20Poly1305_Mode::name
std::string name() const override
Definition: chacha20poly1305.h:34
Botan::ChaCha20Poly1305_Mode::set_associated_data
void set_associated_data(const uint8_t ad[], size_t ad_len) override
Definition: chacha20poly1305.cpp:46
Botan::ChaCha20Poly1305_Mode::m_chacha
std::unique_ptr< StreamCipher > m_chacha
Definition: chacha20poly1305.h:50
Botan::ChaCha20Poly1305_Mode::cfrg_version
bool cfrg_version() const
Definition: chacha20poly1305.h:59
Botan::ChaCha20Poly1305_Mode::tag_size
size_t tag_size() const override
Definition: chacha20poly1305.h:43
Botan::ChaCha20Poly1305_Mode::update_len
void update_len(size_t len)
Definition: chacha20poly1305.cpp:53
Botan::ChaCha20Poly1305_Mode::reset
void reset() override
Definition: chacha20poly1305.cpp:34
Botan::ChaCha20Poly1305_Mode::clear
void clear() override
Definition: chacha20poly1305.cpp:27
Botan::ChaCha20Poly1305_Mode::m_poly1305
std::unique_ptr< MessageAuthenticationCode > m_poly1305
Definition: chacha20poly1305.h:51
Botan::ChaCha20Poly1305_Mode::m_nonce_len
size_t m_nonce_len
Definition: chacha20poly1305.h:56
Botan::Cipher_Mode::update
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:112
Botan::Invalid_Authentication_Tag
Definition: exceptn.h:291
Botan::Invalid_IV_Length
Definition: exceptn.h:162
Botan::Invalid_State
Definition: exceptn.h:216
Botan::MessageAuthenticationCode
Definition: mac.h:23
Botan::StreamCipher
Definition: stream_cipher.h:22
Botan
Definition: alg_id.cpp:13
Botan::secure_scrub_memory
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:66
Botan::constant_time_compare
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
Botan::store_le
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:454
Botan::secure_vector
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65