• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5230455705

10 Jun 2023 02:30PM UTC coverage: 91.715% (-0.03%) from 91.746%
5230455705

push

github

randombit
Merge GH #3584 Change clang-format AllowShortFunctionsOnASingleLine config from All to Inline

77182 of 84154 relevant lines covered (91.72%)

11975295.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.04
/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp
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/internal/chacha20poly1305.h>
10

11
#include <botan/internal/loadstor.h>
12

13
namespace Botan {
14

15
ChaCha20Poly1305_Mode::ChaCha20Poly1305_Mode() :
13,099✔
16
      m_chacha(StreamCipher::create("ChaCha")), m_poly1305(MessageAuthenticationCode::create("Poly1305")) {
13,099✔
17
   if(!m_chacha || !m_poly1305) {
13,099✔
18
      throw Algorithm_Not_Found("ChaCha20Poly1305");
×
19
   }
20
}
13,099✔
21

22
bool ChaCha20Poly1305_Mode::valid_nonce_length(size_t n) const {
109,989✔
23
   return (n == 8 || n == 12 || n == 24);
109,989✔
24
}
25

26
size_t ChaCha20Poly1305_Mode::update_granularity() const {
10,997✔
27
   return 1;
10,997✔
28
}
29

30
size_t ChaCha20Poly1305_Mode::ideal_granularity() const {
9,450✔
31
   return 128;
9,450✔
32
}
33

34
void ChaCha20Poly1305_Mode::clear() {
3,150✔
35
   m_chacha->clear();
3,150✔
36
   m_poly1305->clear();
3,150✔
37
   reset();
3,150✔
38
}
3,150✔
39

40
void ChaCha20Poly1305_Mode::reset() {
20,295✔
41
   m_ad.clear();
20,295✔
42
   m_ctext_len = 0;
20,295✔
43
   m_nonce_len = 0;
20,295✔
44
}
20,295✔
45

46
bool ChaCha20Poly1305_Mode::has_keying_material() const {
11,025✔
47
   return m_chacha->has_keying_material();
11,025✔
48
}
49

50
void ChaCha20Poly1305_Mode::key_schedule(const uint8_t key[], size_t length) {
79,885✔
51
   m_chacha->set_key(key, length);
79,885✔
52
}
79,885✔
53

54
void ChaCha20Poly1305_Mode::set_associated_data_n(size_t idx, std::span<const uint8_t> ad) {
111,446✔
55
   BOTAN_ARG_CHECK(idx == 0, "ChaCha20Poly1305: cannot handle non-zero index in set_associated_data_n");
111,446✔
56
   if(m_ctext_len > 0 || m_nonce_len > 0) {
111,446✔
57
      throw Invalid_State("Cannot set AD for ChaCha20Poly1305 while processing a message");
3,150✔
58
   }
59
   m_ad.assign(ad.begin(), ad.end());
108,296✔
60
}
108,296✔
61

62
void ChaCha20Poly1305_Mode::update_len(size_t len) {
204,262✔
63
   uint8_t len8[8] = {0};
204,262✔
64
   store_le(static_cast<uint64_t>(len), len8);
102,118✔
65
   m_poly1305->update(len8, 8);
204,262✔
66
}
102,118✔
67

68
void ChaCha20Poly1305_Mode::start_msg(const uint8_t nonce[], size_t nonce_len) {
108,414✔
69
   if(!valid_nonce_length(nonce_len)) {
108,414✔
70
      throw Invalid_IV_Length(name(), nonce_len);
×
71
   }
72

73
   m_ctext_len = 0;
108,414✔
74
   m_nonce_len = nonce_len;
108,414✔
75

76
   m_chacha->set_iv(nonce, nonce_len);
108,414✔
77

78
   uint8_t first_block[64];
108,414✔
79
   m_chacha->write_keystream(first_block, sizeof(first_block));
108,414✔
80

81
   m_poly1305->set_key(first_block, 32);
108,414✔
82
   // Remainder of first block is discarded
83
   secure_scrub_memory(first_block, sizeof(first_block));
108,414✔
84

85
   m_poly1305->update(m_ad);
108,414✔
86

87
   if(cfrg_version()) {
108,414✔
88
      if(m_ad.size() % 16) {
108,394✔
89
         const uint8_t zeros[16] = {0};
101,836✔
90
         m_poly1305->update(zeros, 16 - m_ad.size() % 16);
101,836✔
91
      }
92
   } else {
93
      update_len(m_ad.size());
20✔
94
   }
95
}
108,414✔
96

97
size_t ChaCha20Poly1305_Encryption::process_msg(uint8_t buf[], size_t sz) {
108,872✔
98
   m_chacha->cipher1(buf, sz);
108,872✔
99
   m_poly1305->update(buf, sz);  // poly1305 of ciphertext
104,147✔
100
   m_ctext_len += sz;
100,997✔
101
   return sz;
100,997✔
102
}
103

104
void ChaCha20Poly1305_Encryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
16,929✔
105
   update(buffer, offset);
16,929✔
106
   if(cfrg_version()) {
12,204✔
107
      if(m_ctext_len % 16) {
12,198✔
108
         const uint8_t zeros[16] = {0};
9,350✔
109
         m_poly1305->update(zeros, 16 - m_ctext_len % 16);
9,350✔
110
      }
111
      update_len(m_ad.size());
12,198✔
112
   }
113
   update_len(m_ctext_len);
12,204✔
114

115
   buffer.resize(buffer.size() + tag_size());
12,204✔
116
   m_poly1305->final(&buffer[buffer.size() - tag_size()]);
12,204✔
117
   m_ctext_len = 0;
12,204✔
118
   m_nonce_len = 0;
12,204✔
119
}
12,204✔
120

121
size_t ChaCha20Poly1305_Decryption::process_msg(uint8_t buf[], size_t sz) {
93,488✔
122
   m_poly1305->update(buf, sz);  // poly1305 of ciphertext
93,488✔
123
   m_chacha->cipher1(buf, sz);
90,338✔
124
   m_ctext_len += sz;
90,338✔
125
   return sz;
90,338✔
126
}
127

128
void ChaCha20Poly1305_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
94,635✔
129
   BOTAN_ARG_CHECK(buffer.size() >= offset, "Offset is out of range");
94,635✔
130
   const size_t sz = buffer.size() - offset;
94,635✔
131
   uint8_t* buf = buffer.data() + offset;
94,635✔
132

133
   BOTAN_ARG_CHECK(sz >= tag_size(), "input did not include the tag");
94,635✔
134

135
   const size_t remaining = sz - tag_size();
91,485✔
136

137
   if(remaining) {
91,485✔
138
      m_poly1305->update(buf, remaining);  // poly1305 of ciphertext
88,213✔
139
      m_chacha->cipher1(buf, remaining);
86,668✔
140
      m_ctext_len += remaining;
86,668✔
141
   }
142

143
   if(cfrg_version()) {
89,940✔
144
      if(m_ctext_len % 16) {
89,900✔
145
         const uint8_t zeros[16] = {0};
86,652✔
146
         m_poly1305->update(zeros, 16 - m_ctext_len % 16);
86,652✔
147
      }
148
      update_len(m_ad.size());
89,900✔
149
   }
150

151
   update_len(m_ctext_len);
89,940✔
152

153
   uint8_t mac[16];
89,910✔
154
   m_poly1305->final(mac);
89,910✔
155

156
   const uint8_t* included_tag = &buf[remaining];
89,910✔
157

158
   m_ctext_len = 0;
89,910✔
159
   m_nonce_len = 0;
89,910✔
160

161
   if(!constant_time_compare(mac, included_tag, tag_size())) {
89,910✔
162
      throw Invalid_Authentication_Tag("ChaCha20Poly1305 tag check failed");
4,738✔
163
   }
164
   buffer.resize(offset + remaining);
85,172✔
165
}
85,172✔
166

167
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc