47 lines
1.6 KiB
C++
47 lines
1.6 KiB
C++
// 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 <stdint.h>
|
|
#include <string.h>
|
|
|
|
#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_
|