Skip to content

Commit

Permalink
refactor: tidy-up
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis committed Oct 11, 2024
1 parent 67efcb5 commit 6cdff99
Showing 1 changed file with 45 additions and 43 deletions.
88 changes: 45 additions & 43 deletions src/dpp/voice/enabled/xchacha20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,13 @@ constexpr size_t CHACHA_NONCE_SIZE = 12;

/**
* @brief Rotates the bits of a 32-bit unsigned integer to the left by a specified number of positions.
* From Google's BoringSSL
* @note From Google's BoringSSL, but made constexpr
*
* @param value value to shift
* @param shift number of bits to shift left by
* @return shifted value
*/
inline uint32_t rotl_u32(uint32_t value, int shift) {
constexpr uint32_t rotl_u32(uint32_t value, int shift) {
#if _MSC_VER
return _rotl(value, shift);
#else
Expand All @@ -66,24 +67,30 @@ inline uint32_t rotl_u32(uint32_t value, int shift) {

/**
* @brief Updates a, b, c, and d with a ChaCha20 quarter round.
* This is black box voodoo from BoringSSL. Do not mess with it,
* or try and optimise it. It is what it is!
* @note This is based on black box voodoo from BoringSSL.
*
* @param x an array forming part of an XChaCha20 nonce
* @param a First word of the quarter-round.
* @param b Second word of the quarter-round.
* @param c Third word of the quarter-round.
* @param d Fourth word of the quarter-round.
*/
#define QUARTERROUND(a, b, c, d) \
x[a] += x[b]; \
x[d] = rotl_u32(x[d] ^ x[a], 16); \
x[c] += x[d]; \
x[b] = rotl_u32(x[b] ^ x[c], 12); \
x[a] += x[b]; \
x[d] = rotl_u32(x[d] ^ x[a], 8); \
x[c] += x[d]; \
constexpr void quarter_round(uint32_t* x, int a, int b, int c, int d) {
x[a] += x[b];
x[d] = rotl_u32(x[d] ^ x[a], 16);
x[c] += x[d];
x[b] = rotl_u32(x[b] ^ x[c], 12);
x[a] += x[b];
x[d] = rotl_u32(x[d] ^ x[a], 8);
x[c] += x[d];
x[b] = rotl_u32(x[b] ^ x[c], 7);
}

/**
* @brief key derivation function that takes a 256-bit key and a 128-bit nonce, producing a 256-bit subkey.
*
* This subkey is then used in the XChaCha20 algorithm to extend the nonce size to 192 bits.
* This is taken from BoringSSL. Do not mess with it.
* @note This based on the function from BoringSSL. Do not mess with it.
* @param out output 32 byte subkey
* @param key input 32 byte key
* @param nonce input 16 byte nonce
Expand All @@ -94,63 +101,63 @@ void hchacha20(unsigned char out[KEY_SIZE], const unsigned char key[KEY_SIZE], c
std::memcpy(&x[4], key, KEY_SIZE);
std::memcpy(&x[CHACHA_NONCE_SIZE], nonce, 16);
for (size_t i = 0; i < 20; i += 2) {
QUARTERROUND(0, 4, 8, 12)
QUARTERROUND(1, 5, 9, 13)
QUARTERROUND(2, 6, 10, 14)
QUARTERROUND(3, 7, 11, 15)
QUARTERROUND(0, 5, 10, 15)
QUARTERROUND(1, 6, 11, 12)
QUARTERROUND(2, 7, 8, 13)
QUARTERROUND(3, 4, 9, 14)
quarter_round(x, 0, 4, 8, 12);
quarter_round(x, 1, 5, 9, 13);
quarter_round(x, 2, 6, 10, 14);
quarter_round(x, 3, 7, 11, 15);
quarter_round(x, 0, 5, 10, 15);
quarter_round(x, 1, 6, 11, 12);
quarter_round(x, 2, 7, 8, 13);
quarter_round(x, 3, 4, 9, 14);
}
std::memcpy(out, &x[0], sizeof(uint32_t) * 4);
std::memcpy(&out[16], &x[CHACHA_NONCE_SIZE], sizeof(uint32_t) * 4);
}

int ssl_crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char *c, unsigned long long *clen, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, unsigned long long adlen, const unsigned char *nsec, const unsigned char *npub, const unsigned char *k) {
unsigned char subkey[KEY_SIZE];
unsigned char sub_key[KEY_SIZE];

Check notice on line 118 in src/dpp/voice/enabled/xchacha20.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/dpp/voice/enabled/xchacha20.cpp#L118

The scope of the variable 'sub_key' can be reduced.
/* Regular ChaCha20-Poly1305 uses 12-byte nonce */
unsigned char chacha_nonce[CHACHA_NONCE_SIZE] = {0};

Check notice on line 120 in src/dpp/voice/enabled/xchacha20.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/dpp/voice/enabled/xchacha20.cpp#L120

The scope of the variable 'chacha_nonce' can be reduced.
EVP_CIPHER_CTX *ctx = nullptr;
int len = 0;
int ciphertext_len = 0;

Check notice on line 123 in src/dpp/voice/enabled/xchacha20.cpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/dpp/voice/enabled/xchacha20.cpp#L123

The scope of the variable 'ciphertext_len' can be reduced.

try {
/* Derive the subkey using HChaCha20 */
hchacha20(subkey, k, npub);
/* Derive the sub-key using HChaCha20 */
hchacha20(sub_key, k, npub);

/* Use the last 8 bytes of the 24-byte XChaCha20 nonce */
std::memcpy(chacha_nonce + 4, npub + ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES, 8);

/* Initialize encryption context with ChaCha20-Poly1305 */
ctx = EVP_CIPHER_CTX_new();
if (!ctx || !EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), nullptr, nullptr, nullptr)) {
if ((ctx == nullptr) || (EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), nullptr, nullptr, nullptr) == 0)) {
throw dpp::encryption_exception("Error initializing encryption context");
}

/* Set key and nonce */
if (!EVP_EncryptInit_ex(ctx, nullptr, nullptr, subkey, chacha_nonce)) {
if (EVP_EncryptInit_ex(ctx, nullptr, nullptr, sub_key, chacha_nonce) == 0) {
throw dpp::encryption_exception("Error setting key and nonce");
}

/* Set additional authenticated data (AAD) */
if (!EVP_EncryptUpdate(ctx, nullptr, &len, ad, static_cast<int>(adlen))) {
if (EVP_EncryptUpdate(ctx, nullptr, &len, ad, static_cast<int>(adlen)) == 0) {
throw dpp::encryption_exception("Error setting additional authenticated data");
}

/* Encrypt the plaintext */
if (!EVP_EncryptUpdate(ctx, c, &len, m, static_cast<int>(mlen))) {
if (EVP_EncryptUpdate(ctx, c, &len, m, static_cast<int>(mlen)) == 0) {
throw dpp::encryption_exception("Error during encryption");
}
ciphertext_len = len;

if (!EVP_EncryptFinal_ex(ctx, c + len, &len)) {
if (EVP_EncryptFinal_ex(ctx, c + len, &len) == 0) {
throw dpp::encryption_exception("Error finalizing encryption");
}
ciphertext_len += len;

/* Get the authentication tag */
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES, c + ciphertext_len)) {
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES, c + ciphertext_len) == 0) {
throw dpp::encryption_exception("Error getting authentication tag");
}

Expand All @@ -165,13 +172,11 @@ int ssl_crypto_aead_xchacha20poly1305_ietf_encrypt(unsigned char *c, unsigned lo
}

EVP_CIPHER_CTX_free(ctx);
/* Safety */
std::memset(subkey, 0, sizeof(subkey));
return 0;
}

int ssl_crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m, unsigned long long *mlen, [[maybe_unused]] unsigned char *nsec, const unsigned char *c, unsigned long long clen, const unsigned char *ad, unsigned long long adlen, const unsigned char *npub, const unsigned char *k) {
unsigned char subkey[KEY_SIZE];
unsigned char sub_key[KEY_SIZE];
/* Regular ChaCha20-Poly1305 uses 12-byte nonce */
unsigned char chacha_nonce[CHACHA_NONCE_SIZE] = {0};
EVP_CIPHER_CTX *ctx = nullptr;
Expand All @@ -184,36 +189,36 @@ int ssl_crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m, unsigned lo
}

try {
/* Derive the subkey using HChaCha20 */
hchacha20(subkey, k, npub);
/* Derive the sub-key using HChaCha20 */
hchacha20(sub_key, k, npub);

/* Use the last 8 bytes of the 24-byte XChaCha20 nonce */
std::memcpy(chacha_nonce + 4, npub + ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES, 8);

/* Initialize decryption context with ChaCha20-Poly1305 */
ctx = EVP_CIPHER_CTX_new();
if (!ctx || !EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), nullptr, nullptr, nullptr)) {
if (!ctx || (EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), nullptr, nullptr, nullptr) == 0)) {
throw dpp::decryption_exception("Error initializing decryption context");
}

/* Set key and nonce */
if (!EVP_DecryptInit_ex(ctx, nullptr, nullptr, subkey, chacha_nonce)) {
if (EVP_DecryptInit_ex(ctx, nullptr, nullptr, sub_key, chacha_nonce) == 0) {
throw dpp::decryption_exception("Error setting key and nonce");
}

/* Set additional authenticated data (AAD) */
if (!EVP_DecryptUpdate(ctx, nullptr, &len, ad, static_cast<int>(adlen))) {
if (EVP_DecryptUpdate(ctx, nullptr, &len, ad, static_cast<int>(adlen)) == 0) {
throw dpp::decryption_exception("Error setting additional authenticated data");
}

/* Decrypt the ciphertext (excluding the tag) */
if (!EVP_DecryptUpdate(ctx, m, &len, c, static_cast<int>(clen - ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES))) {
if (EVP_DecryptUpdate(ctx, m, &len, c, static_cast<int>(clen - ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES)) == 0) {
throw dpp::decryption_exception("Error during decryption");
}
plaintext_len = len;

/* Set the expected tag */
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES, const_cast<unsigned char *>(c + clen - ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES))) {
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES, const_cast<unsigned char *>(c + clen - ssl_crypto_aead_xchacha20poly1305_IETF_ABYTES)) == 0) {
throw dpp::decryption_exception("Error setting authentication tag");
}

Expand All @@ -232,8 +237,5 @@ int ssl_crypto_aead_xchacha20poly1305_ietf_decrypt(unsigned char *m, unsigned lo
}

EVP_CIPHER_CTX_free(ctx);
/* Safety */
std::memset(subkey, 0, sizeof(subkey));

return 0;
}

0 comments on commit 6cdff99

Please sign in to comment.