diff --git a/src/dpp/dave/common.h b/src/dpp/dave/common.h index 35db54632f..6700a97939 100755 --- a/src/dpp/dave/common.h +++ b/src/dpp/dave/common.h @@ -64,31 +64,31 @@ using roster_map = std::map>; // Return type for functions producing RosterMap or hard or soft failures using roster_variant = std::variant; -constexpr magic_marker kMarkerBytes = 0xFAFA; +constexpr magic_marker MARKER_BYTES = 0xFAFA; // Layout constants -constexpr size_t kAesGcm128KeyBytes = 16; -constexpr size_t kAesGcm128NonceBytes = 12; -constexpr size_t kAesGcm128TruncatedSyncNonceBytes = 4; -constexpr size_t kAesGcm128TruncatedSyncNonceOffset = kAesGcm128NonceBytes - kAesGcm128TruncatedSyncNonceBytes; -constexpr size_t kAesGcm128TruncatedTagBytes = 8; -constexpr size_t kRatchetGenerationBytes = 1; -constexpr size_t kRatchetGenerationShiftBits = 8 * (kAesGcm128TruncatedSyncNonceBytes - kRatchetGenerationBytes); -constexpr size_t kSupplementalBytes = kAesGcm128TruncatedTagBytes + sizeof(supplemental_bytes_size) + sizeof(magic_marker); -constexpr size_t kTransformPaddingBytes = 64; +constexpr size_t AES_GCM_128_KEY_BYTES = 16; +constexpr size_t AES_GCM_128_NONCE_BYTES = 12; +constexpr size_t AES_GCM_128_TRUNCATED_SYNC_NONCE_BYTES = 4; +constexpr size_t AES_GCM_128_TRUNCATED_SYNC_NONCE_OFFSET = AES_GCM_128_NONCE_BYTES - AES_GCM_128_TRUNCATED_SYNC_NONCE_BYTES; +constexpr size_t AES_GCM_127_TRUNCATED_TAG_BYTES = 8; +constexpr size_t RATCHET_GENERATION_BYTES = 1; +constexpr size_t RATCHET_GENERATION_SHIFT_BITS = 8 * (AES_GCM_128_TRUNCATED_SYNC_NONCE_BYTES - RATCHET_GENERATION_BYTES); +constexpr size_t SUPPLEMENTAL_BYTES = AES_GCM_127_TRUNCATED_TAG_BYTES + sizeof(supplemental_bytes_size) + sizeof(magic_marker); +constexpr size_t TRANSFORM_PADDING_BYTES = 64; // Timing constants -constexpr auto kDefaultTransitionDuration = std::chrono::seconds(10); -constexpr auto kCryptorExpiry = std::chrono::seconds(10); +constexpr auto DEFAULT_TRANSITION_EXPIRY = std::chrono::seconds(10); +constexpr auto CIPHER_EXPIRY = std::chrono::seconds(10); // Behavior constants -constexpr auto kInitTransitionId = 0; -constexpr auto kDisabledVersion = 0; -constexpr auto kMaxGenerationGap = 250; -constexpr auto kMaxMissingNonces = 1000; -constexpr auto kGenerationWrap = 1 << (8 * kRatchetGenerationBytes); -constexpr auto kMaxFramesPerSecond = 50 + 2 * 60; // 50 audio frames + 2 * 60fps video streams -constexpr std::array kOpusSilencePacket = {0xF8, 0xFF, 0xFE}; +constexpr auto INIT_TRANSITION_ID = 0; +constexpr auto DISABLED_VERSION = 0; +constexpr auto MAX_GENERATION_GAP = 250; +constexpr auto MAX_MISSING_NONCES = 1000; +constexpr auto GENERATION_WRAP = 1 << (8 * RATCHET_GENERATION_BYTES); +constexpr auto MAX_FRAMES_PER_SECOND = 50 + 2 * 60; // 50 audio frames + 2 * 60fps video streams +constexpr std::array OPUS_SILENCE_PACKET = {0xF8, 0xFF, 0xFE}; // Utility routine for variant return types template inline std::optional get_optional(V&& variant) diff --git a/src/dpp/dave/cryptor_manager.cpp b/src/dpp/dave/cryptor_manager.cpp index 821bc24bf4..3433262f13 100755 --- a/src/dpp/dave/cryptor_manager.cpp +++ b/src/dpp/dave/cryptor_manager.cpp @@ -39,17 +39,17 @@ KeyGeneration compute_wrapped_generation(KeyGeneration oldest, KeyGeneration gen { // Assume generation is greater than or equal to oldest, this may be wrong in a few cases but // will be caught by the max generation gap check. - auto remainder = oldest % kGenerationWrap; - auto factor = oldest / kGenerationWrap + (generation < remainder ? 1 : 0); - return factor * kGenerationWrap + generation; + auto remainder = oldest % GENERATION_WRAP; + auto factor = oldest / GENERATION_WRAP + (generation < remainder ? 1 : 0); + return factor * GENERATION_WRAP + generation; } big_nonce compute_wrapped_big_nonce(KeyGeneration generation, truncated_sync_nonce nonce) { // Remove the generation bits from the nonce - auto maskedNonce = nonce & ((1 << kRatchetGenerationShiftBits) - 1); + auto maskedNonce = nonce & ((1 << RATCHET_GENERATION_SHIFT_BITS) - 1); // Add the wrapped generation bits back in - return static_cast(generation) << kRatchetGenerationShiftBits | maskedNonce; + return static_cast(generation) << RATCHET_GENERATION_SHIFT_BITS | maskedNonce; } aead_cipher_manager::aead_cipher_manager(const clock_interface& clock, std::unique_ptr keyRatchet) @@ -81,7 +81,7 @@ cipher_interface* aead_cipher_manager::get_cipher(KeyGeneration generation) return nullptr; } - if (generation > newestGeneration_ + kMaxGenerationGap) { + if (generation > newestGeneration_ + MAX_GENERATION_GAP) { DISCORD_LOG(LS_INFO) << "Received frame with future generation: " << generation << ", newest generation: " << newestGeneration_; return nullptr; @@ -89,8 +89,8 @@ cipher_interface* aead_cipher_manager::get_cipher(KeyGeneration generation) auto ratchetLifetimeSec = std::chrono::duration_cast(clock_.now() - ratchetCreation_).count(); - auto maxLifetimeFrames = kMaxFramesPerSecond * ratchetLifetimeSec; - auto maxLifetimeGenerations = maxLifetimeFrames >> kRatchetGenerationShiftBits; + auto maxLifetimeFrames = MAX_FRAMES_PER_SECOND * ratchetLifetimeSec; + auto maxLifetimeGenerations = maxLifetimeFrames >> RATCHET_GENERATION_SHIFT_BITS; if (generation > maxLifetimeGenerations) { DISCORD_LOG(LS_INFO) << "Received frame with generation " << generation << " beyond ratchet max lifetime generations: " @@ -119,7 +119,7 @@ void aead_cipher_manager::report_cipher_success(KeyGeneration generation, trunca newestProcessedNonce_ = bigNonce; } else if (bigNonce > *newestProcessedNonce_) { - auto oldestMissingNonce = bigNonce > kMaxMissingNonces ? bigNonce - kMaxMissingNonces : 0; + auto oldestMissingNonce = bigNonce > MAX_MISSING_NONCES ? bigNonce - MAX_MISSING_NONCES : 0; while (!missingNonces_.empty() && missingNonces_.front() < oldestMissingNonce) { missingNonces_.pop_front(); @@ -148,7 +148,7 @@ void aead_cipher_manager::report_cipher_success(KeyGeneration generation, trunca newestGeneration_ = generation; // Update the expiry time for all old cryptors - const auto expiryTime = clock_.now() + kCryptorExpiry; + const auto expiryTime = clock_.now() + CIPHER_EXPIRY; for (auto& [gen, cryptor] : cryptors_) { if (gen < newestGeneration_) { DISCORD_LOG(LS_INFO) << "Updating expiry for cryptor, generation: " << gen; @@ -173,7 +173,7 @@ aead_cipher_manager::expiring_cipher aead_cipher_manager::make_expiring_cipher(K // to a newer generation if (generation < newestGeneration_) { DISCORD_LOG(LS_INFO) << "Creating cryptor for old generation: " << generation; - expiryTime = clock_.now() + kCryptorExpiry; + expiryTime = clock_.now() + CIPHER_EXPIRY; } else { DISCORD_LOG(LS_INFO) << "Creating cryptor for new generation: " << generation; diff --git a/src/dpp/dave/decryptor.cpp b/src/dpp/dave/decryptor.cpp index 933b75dbe5..6b61c4fd08 100755 --- a/src/dpp/dave/decryptor.cpp +++ b/src/dpp/dave/decryptor.cpp @@ -80,8 +80,8 @@ size_t decryptor::decrypt(media_type mediaType, ScopeExit cleanup([&] { return_frame_processor(std::move(localFrame)); }); // Skip decrypting for silence frames - if (mediaType == media_audio && encryptedFrame.size() == kOpusSilencePacket.size() && - std::memcmp(encryptedFrame.data(), kOpusSilencePacket.data(), kOpusSilencePacket.size()) == 0) { + if (mediaType == media_audio && encryptedFrame.size() == OPUS_SILENCE_PACKET.size() && + std::memcmp(encryptedFrame.data(), OPUS_SILENCE_PACKET.data(), OPUS_SILENCE_PACKET.size()) == 0) { DISCORD_LOG(LS_VERBOSE) << "decrypt skipping silence of size: " << encryptedFrame.size(); if (encryptedFrame.data() != frame.data()) { std::memcpy(frame.data(), encryptedFrame.data(), encryptedFrame.size()); @@ -168,15 +168,15 @@ bool decryptor::decrypt_impl(aead_cipher_manager& cipher_manager, auto plaintext = encryptedFrame.GetPlaintext(); // expand the truncated nonce to the full sized one needed for decryption - auto nonceBuffer = std::array(); - memcpy(nonceBuffer.data() + kAesGcm128TruncatedSyncNonceOffset, - &truncatedNonce, - kAesGcm128TruncatedSyncNonceBytes); + auto nonceBuffer = std::array(); + memcpy(nonceBuffer.data() + AES_GCM_128_TRUNCATED_SYNC_NONCE_OFFSET, + &truncatedNonce, + AES_GCM_128_TRUNCATED_SYNC_NONCE_BYTES); auto nonceBufferView = make_array_view(nonceBuffer.data(), nonceBuffer.size()); auto generation = - cipher_manager.compute_wrapped_generation(truncatedNonce >> kRatchetGenerationShiftBits); + cipher_manager.compute_wrapped_generation(truncatedNonce >> RATCHET_GENERATION_SHIFT_BITS); if (!cipher_manager.can_process_nonce(generation, truncatedNonce)) { DISCORD_LOG(LS_INFO) << "decrypt failed, cannot process nonce: " << truncatedNonce; diff --git a/src/dpp/dave/decryptor.h b/src/dpp/dave/decryptor.h index dab2ca3f1a..e4cd550e75 100755 --- a/src/dpp/dave/decryptor.h +++ b/src/dpp/dave/decryptor.h @@ -56,9 +56,9 @@ class decryptor { using Duration = std::chrono::seconds; void transition_to_key_ratchet(std::unique_ptr keyRatchet, - Duration transitionExpiry = kDefaultTransitionDuration); + Duration transitionExpiry = DEFAULT_TRANSITION_EXPIRY); void transition_to_passthrough_mode(bool passthroughMode, - Duration transitionExpiry = kDefaultTransitionDuration); + Duration transitionExpiry = DEFAULT_TRANSITION_EXPIRY); size_t decrypt(media_type mediaType, array_view encryptedFrame, diff --git a/src/dpp/dave/encryptor.cpp b/src/dpp/dave/encryptor.cpp index 3981363b28..2edd31c8eb 100755 --- a/src/dpp/dave/encryptor.cpp +++ b/src/dpp/dave/encryptor.cpp @@ -106,9 +106,9 @@ int encryptor::encrypt(media_type mediaType, auto ciphertextBuffer = make_array_view(ciphertextBytes.data(), ciphertextBytes.size()); auto frameSize = encryptedBytes.size() + unencryptedBytes.size(); - auto tagBuffer = make_array_view(encryptedFrame.data() + frameSize, kAesGcm128TruncatedTagBytes); + auto tagBuffer = make_array_view(encryptedFrame.data() + frameSize, AES_GCM_127_TRUNCATED_TAG_BYTES); - auto nonceBuffer = std::array(); + auto nonceBuffer = std::array(); auto nonceBufferView = make_array_view(nonceBuffer.data(), nonceBuffer.size()); constexpr auto MAX_CIPHERTEXT_VALIDATION_RETRIES = 10; @@ -133,9 +133,9 @@ int encryptor::encrypt(media_type mediaType, // write the truncated nonce to our temporary full nonce array // (since the encryption call expects a full size nonce) - std::memcpy(nonceBuffer.data() + kAesGcm128TruncatedSyncNonceOffset, - &truncatedNonce, - kAesGcm128TruncatedSyncNonceBytes); + std::memcpy(nonceBuffer.data() + AES_GCM_128_TRUNCATED_SYNC_NONCE_OFFSET, + &truncatedNonce, + AES_GCM_128_TRUNCATED_SYNC_NONCE_BYTES); // encrypt the plaintext, adding the unencrypted header to the tag bool success = cryptor->encrypt( @@ -182,13 +182,13 @@ int encryptor::encrypt(media_type mediaType, // write the supplemental bytes size supplemental_bytes_size supplementalBytes = - kSupplementalBytes + nonceSize + unencryptedRangesSize; + SUPPLEMENTAL_BYTES + nonceSize + unencryptedRangesSize; std::memcpy(supplementalBytesBuffer.data(), &supplementalBytes, sizeof(supplemental_bytes_size)); // write the marker bytes, ends the frame - std::memcpy(markerBytesBuffer.data(), &kMarkerBytes, sizeof(magic_marker)); + std::memcpy(markerBytesBuffer.data(), &MARKER_BYTES, sizeof(magic_marker)); - auto encryptedFrameBytes = reconstructedFrameSize + kAesGcm128TruncatedTagBytes + + auto encryptedFrameBytes = reconstructedFrameSize + AES_GCM_127_TRUNCATED_TAG_BYTES + nonceSize + unencryptedRangesSize + sizeof(supplemental_bytes_size) + sizeof(magic_marker); if (codec_utils::validate_encrypted_frame( @@ -229,7 +229,7 @@ int encryptor::encrypt(media_type mediaType, size_t encryptor::get_max_ciphertext_byte_size(media_type mediaType, size_t frameSize) { - return frameSize + kSupplementalBytes + kTransformPaddingBytes; + return frameSize + SUPPLEMENTAL_BYTES + TRANSFORM_PADDING_BYTES; } void encryptor::assign_ssrc_to_codec(uint32_t ssrc, Codec codecType) @@ -287,7 +287,7 @@ encryptor::cryptor_and_nonce encryptor::get_next_cryptor_and_nonce() } auto generation = compute_wrapped_generation(currentKeyGeneration_, - ++truncatedNonce_ >> kRatchetGenerationShiftBits); + ++truncatedNonce_ >> RATCHET_GENERATION_SHIFT_BITS); if (generation != currentKeyGeneration_ || !cryptor_) { currentKeyGeneration_ = generation; diff --git a/src/dpp/dave/frame_processors.cpp b/src/dpp/dave/frame_processors.cpp index e890c52698..66d9f121c8 100755 --- a/src/dpp/dave/frame_processors.cpp +++ b/src/dpp/dave/frame_processors.cpp @@ -199,7 +199,7 @@ void inbound_frame_processor::ParseFrame(array_view frame) Clear(); constexpr auto MinSupplementalBytesSize = - kAesGcm128TruncatedTagBytes + sizeof(supplemental_bytes_size) + sizeof(magic_marker); + AES_GCM_127_TRUNCATED_TAG_BYTES + sizeof(supplemental_bytes_size) + sizeof(magic_marker); if (frame.size() < MinSupplementalBytesSize) { DISCORD_LOG(LS_WARNING) << "Encrypted frame is too small to contain min supplemental bytes"; return; @@ -207,7 +207,7 @@ void inbound_frame_processor::ParseFrame(array_view frame) // Check the frame ends with the magic marker auto magicMarkerBuffer = frame.end() - sizeof(magic_marker); - if (memcmp(magicMarkerBuffer, &kMarkerBytes, sizeof(magic_marker)) != 0) { + if (memcmp(magicMarkerBuffer, &MARKER_BYTES, sizeof(magic_marker)) != 0) { return; } @@ -235,10 +235,10 @@ void inbound_frame_processor::ParseFrame(array_view frame) assert(frame.begin() <= supplementalBytesBuffer && supplementalBytesBuffer <= frame.end()); // Read the tag - tag_ = make_array_view(supplementalBytesBuffer, kAesGcm128TruncatedTagBytes); + tag_ = make_array_view(supplementalBytesBuffer, AES_GCM_127_TRUNCATED_TAG_BYTES); // Read the nonce - auto nonceBuffer = supplementalBytesBuffer + kAesGcm128TruncatedTagBytes; + auto nonceBuffer = supplementalBytesBuffer + AES_GCM_127_TRUNCATED_TAG_BYTES; assert(frame.begin() <= nonceBuffer && nonceBuffer <= frame.end()); auto readAt = nonceBuffer; auto end = supplementalBytesSizeBuffer; diff --git a/src/dpp/dave/mls_key_ratchet.cpp b/src/dpp/dave/mls_key_ratchet.cpp index 3900b7e1eb..eb1d34b2b3 100755 --- a/src/dpp/dave/mls_key_ratchet.cpp +++ b/src/dpp/dave/mls_key_ratchet.cpp @@ -43,7 +43,7 @@ encryption_key MlsKeyRatchet::GetKey(KeyGeneration generation) noexcept try { auto keyAndNonce = hashRatchet_.get(generation); - assert(keyAndNonce.key.size() >= kAesGcm128KeyBytes); + assert(keyAndNonce.key.size() >= AES_GCM_128_KEY_BYTES); return std::move(keyAndNonce.key.as_vec()); } catch (const std::exception& e) { diff --git a/src/dpp/dave/openssl_aead_cipher.cpp b/src/dpp/dave/openssl_aead_cipher.cpp index 94f921fb5f..545e04d7ee 100755 --- a/src/dpp/dave/openssl_aead_cipher.cpp +++ b/src/dpp/dave/openssl_aead_cipher.cpp @@ -60,7 +60,7 @@ bool openssl_aead_cipher::encrypt(byte_view ciphertextBufferOut, const_byte_view /* * Set IV length */ - if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_SET_IVLEN, kAesGcm128NonceBytes, nullptr) == 0) { + if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_SET_IVLEN, AES_GCM_128_NONCE_BYTES, nullptr) == 0) { PrintSSLErrors(); return false; } @@ -99,7 +99,7 @@ bool openssl_aead_cipher::encrypt(byte_view ciphertextBufferOut, const_byte_view } /* Get the tag */ - if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_GET_TAG, kAesGcm128TruncatedTagBytes, tagBufferOut.data()) == 0) { + if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_GET_TAG, AES_GCM_127_TRUNCATED_TAG_BYTES, tagBufferOut.data()) == 0) { PrintSSLErrors(); return false; } @@ -118,7 +118,7 @@ bool openssl_aead_cipher::decrypt(byte_view plaintextBufferOut, const_byte_view } /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ - if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_SET_IVLEN, kAesGcm128NonceBytes, nullptr) == 0) { + if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_SET_IVLEN, AES_GCM_128_NONCE_BYTES, nullptr) == 0) { PrintSSLErrors(); return false; } @@ -148,7 +148,7 @@ bool openssl_aead_cipher::decrypt(byte_view plaintextBufferOut, const_byte_view } /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ - if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_SET_TAG, kAesGcm128TruncatedTagBytes, (void*)tagBuffer.data()) == 0) { + if (EVP_CIPHER_CTX_ctrl(cipherCtx_, EVP_CTRL_GCM_SET_TAG, AES_GCM_127_TRUNCATED_TAG_BYTES, (void*)tagBuffer.data()) == 0) { PrintSSLErrors(); return false; } diff --git a/src/dpp/dave/session.cpp b/src/dpp/dave/session.cpp index a26896acdb..e52a5ac16b 100755 --- a/src/dpp/dave/session.cpp +++ b/src/dpp/dave/session.cpp @@ -696,7 +696,7 @@ std::unique_ptr Session::GetKeyRatchet(std::string const& userId) c // generate the base secret for the hash ratchet auto baseSecret = - currentState_->do_export(Session::USER_MEDIA_KEY_BASE_LABEL, userIdBytes, kAesGcm128KeyBytes); + currentState_->do_export(Session::USER_MEDIA_KEY_BASE_LABEL, userIdBytes, AES_GCM_128_KEY_BYTES); // this assumes the MLS ciphersuite produces a kAesGcm128KeyBytes sized key // would need to be updated to a different ciphersuite if there's a future mismatch