mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 00:00:29 +03:00
AEAD/Chacha20/Poly1305 encrypt multiple buffers
This commit is contained in:
parent
0c9ebc36d4
commit
e68f1dbc99
@ -50,44 +50,26 @@ void quarterround(uint32_t *x, int a, int b, int c, int d)
|
|||||||
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State_t
|
|
||||||
{
|
|
||||||
State_t() {};
|
|
||||||
State_t(State_t &&) = delete;
|
|
||||||
|
|
||||||
State_t & operator += (const State_t & other)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 16; i++)
|
|
||||||
data[i] += other.data[i];
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Copy(const State_t & other)
|
struct Block_t
|
||||||
{
|
{
|
||||||
memcpy(data, other.data, sizeof(uint32_t) * 16);
|
Block_t() {};
|
||||||
}
|
Block_t(Block_t &&) = delete;
|
||||||
uint32_t data[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Block_t
|
uint8_t data[blocksize];
|
||||||
{
|
|
||||||
Block_t() {};
|
|
||||||
Block_t(Block_t &&) = delete;
|
|
||||||
|
|
||||||
uint8_t data[blocksize];
|
void operator << (const Chacha20State & st)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
u32t8le(st.data[i], data + (i << 2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void operator << (const State_t & st)
|
void block(const Chacha20State &input, Block_t & block, int rounds)
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 16; i++)
|
|
||||||
u32t8le(st.data[i], data + (i << 2));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void block(const State_t &input, Block_t & block, int rounds)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
State_t x;
|
Chacha20State x;
|
||||||
x.Copy(input);
|
x.Copy(input);
|
||||||
|
|
||||||
for (i = rounds; i > 0; i -= 2)
|
for (i = rounds; i > 0; i -= 2)
|
||||||
@ -107,44 +89,41 @@ void block(const State_t &input, Block_t & block, int rounds)
|
|||||||
}
|
}
|
||||||
} // namespace chacha
|
} // namespace chacha
|
||||||
|
|
||||||
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
||||||
|
{
|
||||||
|
state.data[0] = 0x61707865;
|
||||||
|
state.data[1] = 0x3320646e;
|
||||||
|
state.data[2] = 0x79622d32;
|
||||||
|
state.data[3] = 0x6b206574;
|
||||||
|
for (size_t i = 0; i < 8; i++)
|
||||||
|
state.data[4 + i] = chacha::u8t32le(key + i * 4);
|
||||||
|
|
||||||
|
state.data[12] = counter;
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
|
||||||
|
{
|
||||||
|
chacha::Block_t block;
|
||||||
|
for (size_t i = 0; i < sz; i += chacha::blocksize)
|
||||||
|
{
|
||||||
|
chacha::block(state, block, chacha::rounds);
|
||||||
|
state.data[12]++;
|
||||||
|
for (size_t j = i; j < i + chacha::blocksize; j++)
|
||||||
|
{
|
||||||
|
if (j >= sz) break;
|
||||||
|
buf[j] ^= block.data[j - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
||||||
|
{
|
||||||
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
Chacha20State state;
|
||||||
{
|
Chacha20Init (state, nonce, key, counter);
|
||||||
chacha::State_t state;
|
Chacha20Encrypt (state, buf, sz);
|
||||||
chacha::Block_t block;
|
}
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
state.data[0] = 0x61707865;
|
|
||||||
state.data[1] = 0x3320646e;
|
|
||||||
state.data[2] = 0x79622d32;
|
|
||||||
state.data[3] = 0x6b206574;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
state.data[4 + i] = chacha::u8t32le(key + i * 4);
|
|
||||||
|
|
||||||
|
|
||||||
state.data[12] = counter;
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < sz; i += chacha::blocksize)
|
|
||||||
{
|
|
||||||
chacha::block(state, block, chacha::rounds);
|
|
||||||
state.data[12]++;
|
|
||||||
for (j = i; j < i + chacha::blocksize; j++)
|
|
||||||
{
|
|
||||||
if (j >= sz) break;
|
|
||||||
buf[j] ^= block.data[j - i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#define LIBI2PD_CHACHA20_H
|
#define LIBI2PD_CHACHA20_H
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
|
||||||
#if LEGACY_OPENSSL
|
#if LEGACY_OPENSSL
|
||||||
@ -19,10 +21,32 @@ namespace crypto
|
|||||||
const std::size_t CHACHA20_KEY_BYTES = 32;
|
const std::size_t CHACHA20_KEY_BYTES = 32;
|
||||||
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
|
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
|
||||||
|
|
||||||
|
struct Chacha20State
|
||||||
|
{
|
||||||
|
Chacha20State () {};
|
||||||
|
Chacha20State (Chacha20State &&) = delete;
|
||||||
|
|
||||||
|
Chacha20State & operator += (const Chacha20State & other)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
data[i] += other.data[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Copy(const Chacha20State & other)
|
||||||
|
{
|
||||||
|
memcpy(data, other.data, sizeof(uint32_t) * 16);
|
||||||
|
}
|
||||||
|
uint32_t data[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
|
||||||
|
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz);
|
||||||
|
|
||||||
/** encrypt buf in place with chacha20 */
|
/** encrypt buf in place with chacha20 */
|
||||||
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1);
|
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1172,6 +1172,55 @@ namespace crypto
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AEADChaCha20Poly1305Encrypt (std::vector<std::pair<void*, std::size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
|
||||||
|
{
|
||||||
|
if (bufs.empty ()) return;
|
||||||
|
#if LEGACY_OPENSSL
|
||||||
|
// generate one time poly key
|
||||||
|
uint64_t polyKey[8];
|
||||||
|
memset(polyKey, 0, sizeof(polyKey));
|
||||||
|
chacha20 ((uint8_t *)polyKey, 64, nonce, key, 0);
|
||||||
|
Poly1305 polyHash (polyKey);
|
||||||
|
// encrypt buffers
|
||||||
|
Chacha20State state;
|
||||||
|
Chacha20Init (state, nonce, key, 1);
|
||||||
|
size_t size = 0;
|
||||||
|
for (auto& it: bufs)
|
||||||
|
{
|
||||||
|
Chacha20Encrypt (state, (uint8_t *)it.first, it.second);
|
||||||
|
polyHash.Update ((uint8_t *)it.first, it.second); // after encryption
|
||||||
|
size += it.second;
|
||||||
|
}
|
||||||
|
// padding
|
||||||
|
uint8_t padding[16];
|
||||||
|
memset (padding, 0, 16);
|
||||||
|
auto rem = size & 0x0F; // %16
|
||||||
|
if (rem)
|
||||||
|
{
|
||||||
|
// padding2
|
||||||
|
rem = 16 - rem;
|
||||||
|
polyHash.Update (padding, rem);
|
||||||
|
}
|
||||||
|
// adLen and msgLen
|
||||||
|
// adLen is always zero
|
||||||
|
htole64buf (padding + 8, size);
|
||||||
|
polyHash.Update (padding, 16);
|
||||||
|
// MAC
|
||||||
|
polyHash.Finish ((uint64_t *)mac);
|
||||||
|
#else
|
||||||
|
int outlen = 0;
|
||||||
|
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
||||||
|
EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
|
||||||
|
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
|
||||||
|
for (auto& it: bufs)
|
||||||
|
EVP_EncryptUpdate(ctx, (uint8_t *)it.first, &outlen, (uint8_t *)it.first, it.second);
|
||||||
|
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
|
||||||
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
|
|
||||||
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/dh.h>
|
#include <openssl/dh.h>
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
@ -282,6 +283,8 @@ namespace crypto
|
|||||||
// AEAD/ChaCha20/Poly1305
|
// AEAD/ChaCha20/Poly1305
|
||||||
bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag
|
bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag
|
||||||
|
|
||||||
|
void AEADChaCha20Poly1305Encrypt (std::vector<std::pair<void*, std::size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
void InitCrypto (bool precomputation);
|
void InitCrypto (bool precomputation);
|
||||||
void TerminateCrypto ();
|
void TerminateCrypto ();
|
||||||
|
@ -51,4 +51,10 @@ int main ()
|
|||||||
uint8_t buf1[114];
|
uint8_t buf1[114];
|
||||||
assert (i2p::crypto::AEADChaCha20Poly1305 (buf, 114, ad, 12, key, nonce, buf1, 114, false));
|
assert (i2p::crypto::AEADChaCha20Poly1305 (buf, 114, ad, 12, key, nonce, buf1, 114, false));
|
||||||
assert (memcmp (buf1, text, 114) == 0);
|
assert (memcmp (buf1, text, 114) == 0);
|
||||||
|
// test encryption of multiple buffers
|
||||||
|
memcpy (buf, text, 114);
|
||||||
|
std::vector<std::pair<void*, std::size_t> > bufs{ std::make_pair (buf, 114) };
|
||||||
|
i2p::crypto::AEADChaCha20Poly1305Encrypt (bufs, key, nonce, buf + 114);
|
||||||
|
i2p::crypto::AEADChaCha20Poly1305 (buf, 114, nullptr, 0, key, nonce, buf1, 114, false);
|
||||||
|
assert (memcmp (buf1, text, 114) == 0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user