// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #ifndef WVCDM_UTIL_ADVANCE_IV_CTR_H_ #define WVCDM_UTIL_ADVANCE_IV_CTR_H_ #include #include #include "string_conversions.h" namespace wvutil { // Advance an IV according to ISO-CENC's CTR modes. The lower half of the IV is // split off and treated as an unsigned 64-bit integer, then incremented by the // number of complete crypto blocks decrypted. The resulting value is then // copied back into the IV over the previous lower half. inline void AdvanceIvCtr(uint8_t (*subsample_iv)[16], size_t bytes) { constexpr size_t kAesBlockSize = 16; constexpr size_t kIvSize = kAesBlockSize; constexpr size_t kCounterIndex = kIvSize / 2; constexpr size_t kCounterSize = kIvSize / 2; uint64_t counter; static_assert( sizeof(*subsample_iv) == kIvSize, "The subsample_iv field is no longer the length of an AES-128 IV."); static_assert(sizeof(counter) == kCounterSize, "A uint64_t failed to be half the size of an AES-128 IV."); // Defensive copy because the elements of the array may not be properly // aligned memcpy(&counter, &(*subsample_iv)[kCounterIndex], kCounterSize); const size_t increment = bytes / kAesBlockSize; // The truncation here is intentional counter = htonll64(ntohll64(counter) + increment); memcpy(&(*subsample_iv)[kCounterIndex], &counter, kCounterSize); } } // namespace wvutil #endif // WVCDM_UTIL_ADVANCE_IV_CTR_H_