7
7
#include < crypto/chacha20.h>
8
8
#include < crypto/common.h>
9
9
10
+ #include < algorithm>
10
11
#include < cstring>
11
12
12
13
#ifndef RFC8439_TIMINGSAFE_BCMP
@@ -57,19 +58,40 @@ std::array<std::byte, POLY1305_KEYLEN> GetPoly1305Key(ChaCha20& c20)
57
58
return polykey;
58
59
}
59
60
60
- void RFC8439Crypt (ChaCha20& c20, const std::vector<Span<const std::byte>>& in_bytes, Span<std::byte> out_bytes)
61
+ void RFC8439Crypt (ChaCha20& c20, const std::vector<Span<const std::byte>>& in_bytes, std::vector< Span<std::byte>>& out_bytes)
61
62
{
62
- size_t total_bytes = 0 ;
63
- for (auto in: in_bytes) {
64
- total_bytes += in.size ();
63
+ size_t total_in_bytes = 0 ;
64
+ for (auto in : in_bytes) {
65
+ total_in_bytes += in.size ();
65
66
}
66
- assert (total_bytes <= out_bytes.size ());
67
- c20.SeekRFC8439 (1 );
67
+ size_t total_out_bytes = 0 ;
68
+ for (auto out : out_bytes) {
69
+ total_out_bytes += out.size ();
70
+ }
71
+ assert (total_in_bytes <= total_out_bytes);
68
72
69
- auto write_pos = out_bytes.data ();
70
- for (auto in: in_bytes) {
71
- c20.Crypt (reinterpret_cast <const unsigned char *>(in.data ()), reinterpret_cast <unsigned char *>(write_pos), in.size ());
72
- write_pos += in.size ();
73
+ c20.SeekRFC8439 (1 );
74
+ size_t in_idx{0 }, in_chunk_pos{0 }, out_idx{0 }, out_chunk_pos{0 };
75
+ while (in_idx < in_bytes.size ()) {
76
+ auto in_chunk = in_bytes[in_idx];
77
+ auto out_chunk = out_bytes[out_idx];
78
+ auto read_pos = in_chunk.begin () + in_chunk_pos;
79
+ auto write_pos = out_chunk.begin () + out_chunk_pos;
80
+ auto num_bytes = std::min (in_chunk.size () - in_chunk_pos, out_chunk.size () - out_chunk_pos);
81
+
82
+ c20.Crypt (reinterpret_cast <const unsigned char *>(read_pos), reinterpret_cast <unsigned char *>(write_pos), num_bytes);
83
+ in_chunk_pos += num_bytes;
84
+ out_chunk_pos += num_bytes;
85
+
86
+ if (in_chunk_pos >= in_chunk.size ()) {
87
+ in_idx++;
88
+ in_chunk_pos = 0 ;
89
+ }
90
+
91
+ if (out_chunk_pos >= out_chunk.size ()) {
92
+ out_idx++;
93
+ out_chunk_pos = 0 ;
94
+ }
73
95
}
74
96
}
75
97
@@ -88,16 +110,24 @@ void RFC8439Encrypt(const Span<const std::byte> aad, const Span<const std::byte>
88
110
}
89
111
90
112
assert (output.size () >= total_bytes + POLY1305_TAGLEN);
91
- RFC8439Crypt (c20, plaintexts, output);
113
+
114
+ std::vector<Span<std::byte>> outs{output};
115
+ RFC8439Crypt (c20, plaintexts, outs);
92
116
ComputeRFC8439Tag (polykey, aad,
93
117
{output.data (), total_bytes},
94
118
{output.data () + total_bytes, POLY1305_TAGLEN});
95
119
}
96
120
97
- bool RFC8439Decrypt (const Span<const std::byte> aad, const Span<const std::byte> key, const std::array<std::byte, 12 >& nonce, const Span<const std::byte> input, Span<std::byte> plaintext )
121
+ bool RFC8439Decrypt (const Span<const std::byte> aad, const Span<const std::byte> key, const std::array<std::byte, 12 >& nonce, const Span<const std::byte> input, std::vector< Span<std::byte>>& plaintexts )
98
122
{
99
123
assert (key.size () == RFC8439_KEYLEN);
100
- assert (plaintext.size () >= input.size () - POLY1305_TAGLEN);
124
+
125
+ size_t total_bytes = 0 ;
126
+ for (auto plaintext: plaintexts) {
127
+ total_bytes += plaintext.size ();
128
+ }
129
+
130
+ assert (total_bytes >= input.size () - POLY1305_TAGLEN);
101
131
102
132
ChaCha20 c20{reinterpret_cast <const unsigned char *>(key.data ()), key.size ()};
103
133
c20.SetRFC8439Nonce (nonce);
@@ -113,6 +143,6 @@ bool RFC8439Decrypt(const Span<const std::byte> aad, const Span<const std::byte>
113
143
}
114
144
115
145
std::vector<Span<const std::byte>> ins{{input.data (), input.size () - POLY1305_TAGLEN}};
116
- RFC8439Crypt (c20, ins, plaintext );
146
+ RFC8439Crypt (c20, ins, plaintexts );
117
147
return true ;
118
148
}
0 commit comments