Skip to content

Commit

Permalink
Change crypto::aes_t to variable size and cleanup some crypto code
Browse files Browse the repository at this point in the history
  • Loading branch information
cgutman committed Jan 20, 2024
1 parent 6b5a712 commit 2f80145
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 45 deletions.
59 changes: 26 additions & 33 deletions src/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,23 @@ namespace crypto {
auto cipher = tagged_cipher.substr(tag_size);
auto tag = tagged_cipher.substr(0, tag_size);

plaintext.resize((cipher.size() + 15) / 16 * 16);
plaintext.resize(round_to_pkcs7_padded(cipher.size()));

int size;
if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &size, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
int update_outlen, final_outlen;

if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &update_outlen, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
return -1;
}

if (EVP_CIPHER_CTX_ctrl(decrypt_ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(), const_cast<char *>(tag.data())) != 1) {
return -1;
}

int len = size;
if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data() + size, &len) != 1) {
if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data() + update_outlen, &final_outlen) != 1) {
return -1;
}

plaintext.resize(size + len);
plaintext.resize(update_outlen + final_outlen);
return 0;
}

Expand All @@ -187,30 +187,27 @@ namespace crypto {
auto tag = tagged_cipher;
auto cipher = tag + tag_size;

int len;
int size = round_to_pkcs7_padded(plaintext.size());
int update_outlen, final_outlen;

// Encrypt into the caller's buffer
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &size, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &update_outlen, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
return -1;
}

// GCM encryption won't ever fill ciphertext here but we have to call it anyway
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + size, &len) != 1) {
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + update_outlen, &final_outlen) != 1) {
return -1;
}

if (EVP_CIPHER_CTX_ctrl(encrypt_ctx.get(), EVP_CTRL_GCM_GET_TAG, tag_size, tag) != 1) {
return -1;
}

return len + size;
return update_outlen + final_outlen;
}

int
ecb_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext) {
int len;

auto fg = util::fail_guard([this]() {
EVP_CIPHER_CTX_reset(decrypt_ctx.get());
});
Expand All @@ -221,19 +218,19 @@ namespace crypto {
}

EVP_CIPHER_CTX_set_padding(decrypt_ctx.get(), padding);
plaintext.resize(round_to_pkcs7_padded(cipher.size()));

int update_outlen, final_outlen;

plaintext.resize((cipher.size() + 15) / 16 * 16);
auto size = (int) plaintext.size();
// Decrypt into the caller's buffer, leaving room for the auth tag to be prepended
if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &size, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &update_outlen, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
return -1;
}

if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data(), &len) != 1) {
if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data() + update_outlen, &final_outlen) != 1) {
return -1;
}

plaintext.resize(len + size);
plaintext.resize(update_outlen + final_outlen);
return 0;
}

Expand All @@ -249,22 +246,20 @@ namespace crypto {
}

EVP_CIPHER_CTX_set_padding(encrypt_ctx.get(), padding);
cipher.resize(round_to_pkcs7_padded(plaintext.size()));

int len;

cipher.resize((plaintext.size() + 15) / 16 * 16);
auto size = (int) cipher.size();
int update_outlen, final_outlen;

// Encrypt into the caller's buffer
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher.data(), &size, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher.data(), &update_outlen, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
return -1;
}

if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher.data() + size, &len) != 1) {
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher.data() + update_outlen, &final_outlen) != 1) {
return -1;
}

cipher.resize(len + size);
cipher.resize(update_outlen + final_outlen);
return 0;
}

Expand All @@ -280,20 +275,18 @@ namespace crypto {
return false;
}

int len;

int size = plaintext.size(); // round_to_pkcs7_padded(plaintext.size());
int update_outlen, final_outlen;

// Encrypt into the caller's buffer
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &size, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &update_outlen, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
return -1;
}

if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + size, &len) != 1) {
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + update_outlen, &final_outlen) != 1) {
return -1;
}

return size + len;
return update_outlen + final_outlen;
}

ecb_t::ecb_t(const aes_t &key, bool padding):
Expand All @@ -309,7 +302,7 @@ namespace crypto {

aes_t
gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &pin) {
aes_t key;
aes_t key(16);

std::string salt_pin;
salt_pin.reserve(salt.size() + pin.size());
Expand Down
2 changes: 1 addition & 1 deletion src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace crypto {

using sha256_t = std::array<std::uint8_t, SHA256_DIGEST_LENGTH>;

using aes_t = std::array<std::uint8_t, 16>;
using aes_t = std::vector<std::uint8_t>;
using x509_t = util::safe_ptr<X509, X509_free>;
using x509_store_t = util::safe_ptr<X509_STORE, X509_STORE_free>;
using x509_store_ctx_t = util::safe_ptr<X509_STORE_CTX, X509_STORE_CTX_free>;
Expand Down
9 changes: 5 additions & 4 deletions src/nvhttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,10 @@ namespace nvhttp {
make_launch_session(bool host_audio, const args_t &args) {
rtsp_stream::launch_session_t launch_session;

auto rikey = util::from_hex_vec(get_arg(args, "rikey"), true);
std::copy(rikey.cbegin(), rikey.cend(), std::back_inserter(launch_session.gcm_key));

launch_session.host_audio = host_audio;
launch_session.gcm_key = util::from_hex<crypto::aes_t>(get_arg(args, "rikey"), true);
std::stringstream mode = std::stringstream(get_arg(args, "mode", "0x0x0"));
// Split mode by the char "x", to populate width/height/fps
int x = 0;
Expand All @@ -296,11 +298,10 @@ namespace nvhttp {
launch_session.av_ping_payload = util::hex_vec(raw_payload);
RAND_bytes((unsigned char *) &launch_session.control_connect_data, sizeof(launch_session.control_connect_data));

launch_session.iv.resize(16);
uint32_t prepend_iv = util::endian::big<uint32_t>(util::from_view(get_arg(args, "rikeyid")));
auto prepend_iv_p = (uint8_t *) &prepend_iv;

auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv));
std::fill(next, std::end(launch_session.iv), 0);
std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv));
return launch_session;
}

Expand Down
14 changes: 7 additions & 7 deletions src/stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ namespace stream {
return plaintext.size();
}

crypto::aes_t iv {};
crypto::aes_t iv(16);
*(std::uint32_t *) iv.data() = util::endian::big<std::uint32_t>(avRiKeyIv + destination->rtp.sequenceNumber);

return cbc.encrypt(std::string_view { (char *) std::begin(plaintext), plaintext.size() }, destination->payload(), &iv);
Expand Down Expand Up @@ -379,7 +379,7 @@ namespace stream {

struct {
crypto::cipher::gcm_t cipher;
crypto::aes_t iv;
crypto::aes_t legacy_input_enc_iv; // Only used when the client doesn't support full control stream encryption

uint32_t connect_data; // Used for new clients with ML_FF_SESSION_ID_V1
std::string expected_peer_address; // Only used for legacy clients without ML_FF_SESSION_ID_V1
Expand Down Expand Up @@ -414,7 +414,7 @@ namespace stream {
return plaintext;
}

crypto::aes_t iv {};
crypto::aes_t iv(16);
auto seq = session->control.seq++;
iv[0] = seq;

Expand Down Expand Up @@ -881,7 +881,7 @@ namespace stream {
std::vector<uint8_t> plaintext;

auto &cipher = session->control.cipher;
auto &iv = session->control.iv;
auto &iv = session->control.legacy_input_enc_iv;
if (cipher.decrypt(tagged_cipher, plaintext, &iv)) {
// something went wrong :(

Expand All @@ -891,7 +891,7 @@ namespace stream {
return;
}

if (tagged_cipher_length >= 16 + sizeof(crypto::aes_t)) {
if (tagged_cipher_length >= 16 + iv.size()) {
std::copy(payload.end() - 16, payload.end(), std::begin(iv));
}

Expand All @@ -915,7 +915,7 @@ namespace stream {
std::string_view tagged_cipher { (char *) header->payload(), (size_t) tagged_cipher_length };

auto &cipher = session->control.cipher;
crypto::aes_t iv {};
crypto::aes_t iv(16);
iv[0] = (std::uint8_t) seq;

// update control sequence
Expand Down Expand Up @@ -1791,7 +1791,7 @@ namespace stream {
session->control.connect_data = launch_session.control_connect_data;
session->control.feedback_queue = mail->queue<platf::gamepad_feedback_msg_t>(mail::gamepad_feedback);
session->control.hdr_queue = mail->event<video::hdr_info_t>(mail::hdr);
session->control.iv = launch_session.iv;
session->control.legacy_input_enc_iv = launch_session.iv;
session->control.cipher = crypto::cipher::gcm_t {
launch_session.gcm_key, false
};
Expand Down

0 comments on commit 2f80145

Please sign in to comment.