OEMCrypto and OPK v19.3
This commit is contained in:
@@ -56,6 +56,18 @@ inline int64_t ntohll64(int64_t x) { return htonll64(x); }
|
||||
// Encode unsigned integer into a big endian formatted string.
|
||||
std::string EncodeUint32(uint32_t u);
|
||||
|
||||
// Converts a byte string representing an ID into a log-friendly form.
|
||||
//
|
||||
// Conversion rules:
|
||||
// 1) empty - returns <empty>
|
||||
// 2) printable ASCII only - original content, surrounded by double
|
||||
// quotes; double quotes and backslashes
|
||||
// are escaped, like C/C++ string literals.
|
||||
// 3) otherwise - Unquoted, hexadecimal encoded string.
|
||||
//
|
||||
// Intended to be used on ID strings which are provided/generated
|
||||
// from sources outside of the CDM.
|
||||
std::string SafeByteIdToString(const std::string& id);
|
||||
std::string SafeByteIdToString(const std::vector<uint8_t>& id);
|
||||
} // namespace wvutil
|
||||
|
||||
#endif // WVCDM_UTIL_STRING_CONVERSIONS_H_
|
||||
|
||||
112
util/include/wv_class_utils.h
Normal file
112
util/include/wv_class_utils.h
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright 2024 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_CLASS_UTILS_HPP_
|
||||
#define WVCDM_UTIL_CLASS_UTILS_HPP_
|
||||
|
||||
// ==== Disallow Operators ====
|
||||
|
||||
#define WVCDM_DISALLOW_COPY(ClassName) \
|
||||
ClassName(const ClassName&) = delete; \
|
||||
ClassName& operator=(const ClassName&) = delete
|
||||
|
||||
#define WVCDM_DISALLOW_MOVE(ClassName) \
|
||||
ClassName(ClassName&&) = delete; \
|
||||
ClassName& operator=(ClassName&&) = delete
|
||||
|
||||
#define WVCDM_DISALLOW_COPY_AND_MOVE(ClassName) \
|
||||
WVCDM_DISALLOW_COPY(ClassName); \
|
||||
WVCDM_DISALLOW_MOVE(ClassName)
|
||||
|
||||
// ==== Default Operators ====
|
||||
|
||||
#define WVCDM_DEFAULT_COPY(ClassName) \
|
||||
ClassName(const ClassName&) = default; \
|
||||
ClassName& operator=(const ClassName&) = default
|
||||
|
||||
#define WVCDM_DEFAULT_MOVE(ClassName) \
|
||||
ClassName(ClassName&&) = default; \
|
||||
ClassName& operator=(ClassName&&) = default
|
||||
|
||||
#define WVCDM_DEFAULT_COPY_AND_MOVE(ClassName) \
|
||||
WVCDM_DEFAULT_COPY(ClassName); \
|
||||
WVCDM_DEFAULT_MOVE(ClassName)
|
||||
|
||||
// ==== Constexpr Default Operators ====
|
||||
|
||||
#define WVCDM_CONSTEXPR_DEFAULT_COPY(ClassName) \
|
||||
constexpr ClassName(const ClassName&) = default; \
|
||||
constexpr ClassName& operator=(const ClassName&) = default
|
||||
|
||||
#define WVCDM_CONSTEXPR_DEFAULT_MOVE(ClassName) \
|
||||
constexpr ClassName(ClassName&&) = default; \
|
||||
constexpr ClassName& operator=(ClassName&&) = default
|
||||
|
||||
#define WVCDM_CONSTEXPR_DEFAULT_COPY_AND_MOVE(ClassName) \
|
||||
WVCDM_CONSTEXPR_DEFAULT_COPY(ClassName); \
|
||||
WVCDM_CONSTEXPR_DEFAULT_MOVE(ClassName)
|
||||
|
||||
// ==== Comparison Operators ====
|
||||
|
||||
// If a class defines the comparison method "bool IsEqualTo() const",
|
||||
// this macro will define the == and != operators for that class.
|
||||
#define WVCDM_DEFINE_EQ_OPERATORS(ClassName) \
|
||||
bool operator==(const ClassName& other) const { return IsEqualTo(other); } \
|
||||
bool operator!=(const ClassName& other) const { return !IsEqualTo(other); }
|
||||
|
||||
// If a class defines the comparison method "int CompareTo() const",
|
||||
// this macro will define the < <= != == >= > operators for that class.
|
||||
#define WVCDM_DEFINE_CMP_OPERATORS(ClassName) \
|
||||
bool operator<(const ClassName& other) const { \
|
||||
return CompareTo(other) < 0; \
|
||||
} \
|
||||
bool operator<=(const ClassName& other) const { \
|
||||
return CompareTo(other) <= 0; \
|
||||
} \
|
||||
bool operator>(const ClassName& other) const { \
|
||||
return CompareTo(other) > 0; \
|
||||
} \
|
||||
bool operator>=(const ClassName& other) const { \
|
||||
return CompareTo(other) >= 0; \
|
||||
}
|
||||
|
||||
// If a class defines the comparison methods "bool IsEqualTo() const"
|
||||
// and "int CompareTo() const", this macro will define the < <= != ==,
|
||||
// >= > operators.
|
||||
#define WVCDM_DEFINE_EQ_AND_CMP_OPERATORS(ClassName) \
|
||||
WVCDM_DEFINE_EQ_OPERATORS(ClassName) \
|
||||
WVCDM_DEFINE_CMP_OPERATORS(ClassName)
|
||||
|
||||
// ==== Constexpr Comparison Operators ====
|
||||
|
||||
// Same as WVCDM_DEFINE_EQ_OPERATORS, but requires class to define
|
||||
// "constexpr bool IsEqualTo() const" method.
|
||||
#define WVCDM_DEFINE_CONSTEXPR_EQ_OPERATORS(ClassName) \
|
||||
constexpr bool operator==(const ClassName& other) const { \
|
||||
return IsEqualTo(other); \
|
||||
} \
|
||||
constexpr bool operator!=(const ClassName& other) const { \
|
||||
return !IsEqualTo(other); \
|
||||
}
|
||||
|
||||
// Same as WVCDM_DEFINE_CMP_OPERATORS, but requires class to define
|
||||
// "constexpr int CompareTo() const" method.
|
||||
#define WVCDM_DEFINE_CONSTEXPR_CMP_OPERATORS(ClassName) \
|
||||
constexpr bool operator<(const ClassName& other) const { \
|
||||
return CompareTo(other) < 0; \
|
||||
} \
|
||||
constexpr bool operator<=(const ClassName& other) const { \
|
||||
return CompareTo(other) <= 0; \
|
||||
} \
|
||||
constexpr bool operator>(const ClassName& other) const { \
|
||||
return CompareTo(other) > 0; \
|
||||
} \
|
||||
constexpr bool operator>=(const ClassName& other) const { \
|
||||
return CompareTo(other) >= 0; \
|
||||
}
|
||||
|
||||
#define WVCDM_DEFINE_CONSTEXPR_EQ_AND_CMP_OPERATORS(ClassName) \
|
||||
WVCDM_DEFINE_CONSTEXPR_EQ_OPERATORS(ClassName) \
|
||||
WVCDM_DEFINE_CONSTEXPR_CMP_OPERATORS(ClassName)
|
||||
|
||||
#endif // WVCDM_UTIL_CLASS_UTILS_HPP_
|
||||
@@ -5,10 +5,11 @@
|
||||
#include "string_conversions.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "log.h"
|
||||
@@ -155,6 +156,61 @@ std::vector<uint8_t> Base64DecodeInternal(const char* encoded, size_t length,
|
||||
result.resize(out_index);
|
||||
return result;
|
||||
}
|
||||
|
||||
// To prevent ID character type conversion errors, these
|
||||
// NormalizeIdChar() functions will safely return the
|
||||
// a char type without changing the byte values.
|
||||
constexpr char NormalizeIdChar(char ch) { return ch; }
|
||||
constexpr char NormalizeIdChar(uint8_t ch) { return static_cast<char>(ch); }
|
||||
|
||||
// An escapable ID char is a character which is considered
|
||||
// "human readable" and can be escaped by inserting a
|
||||
// backslash character before it.
|
||||
template <typename CharType>
|
||||
constexpr bool IsEscapableIdChar(CharType ch) {
|
||||
const char nch = NormalizeIdChar(ch);
|
||||
return nch == '"' || nch == '\\';
|
||||
}
|
||||
|
||||
// A "human readable" ID character is any ASCII character
|
||||
// which produces a glyph or a space character.
|
||||
template <typename CharType>
|
||||
bool IsHumanReadableIdChar(CharType ch) {
|
||||
const char nch = NormalizeIdChar(ch);
|
||||
return isgraph(nch) || nch == ' ';
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
std::string SafeByteIdToStringInternal(const Container& id) {
|
||||
using CharType = typename Container::value_type;
|
||||
if (id.empty()) {
|
||||
return "<empty>";
|
||||
}
|
||||
|
||||
// Check if already human readable.
|
||||
const bool human_readable =
|
||||
std::all_of(id.begin(), id.end(), IsHumanReadableIdChar<CharType>);
|
||||
if (!human_readable) {
|
||||
// For non-human readable IDs, just return the hex encoded version.
|
||||
return b2a_hex(id);
|
||||
}
|
||||
|
||||
// For human readable IDs, add quotes, and escape any double quotes
|
||||
// and backslashes.
|
||||
const size_t escape_count =
|
||||
std::count_if(id.begin(), id.end(), IsEscapableIdChar<CharType>);
|
||||
std::string result;
|
||||
result.reserve(id.size() + escape_count + 2);
|
||||
result.push_back('"');
|
||||
for (const auto& ch : id) {
|
||||
if (IsEscapableIdChar(ch)) {
|
||||
result.push_back('\\');
|
||||
}
|
||||
result.push_back(ch);
|
||||
}
|
||||
result.push_back('"');
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// converts an ascii hex string(2 bytes per digit) into a decimal byte string
|
||||
@@ -340,4 +396,11 @@ std::string EncodeUint32(uint32_t u) {
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string SafeByteIdToString(const std::string& id) {
|
||||
return SafeByteIdToStringInternal(id);
|
||||
}
|
||||
|
||||
std::string SafeByteIdToString(const std::vector<uint8_t>& id) {
|
||||
return SafeByteIdToStringInternal(id);
|
||||
}
|
||||
} // namespace wvutil
|
||||
|
||||
@@ -189,4 +189,115 @@ TEST_F(HtoNLL64Test, NegativeNumber) {
|
||||
int64_t host_byte_order = htonll64(*network_byte_order);
|
||||
EXPECT_EQ(-0x01FdFcFbFaF9F8F8, host_byte_order);
|
||||
}
|
||||
|
||||
TEST(SafeByteIdToString, EmptyId) {
|
||||
const std::string kEmptyString;
|
||||
EXPECT_EQ(SafeByteIdToString(kEmptyString), "<empty>");
|
||||
|
||||
const std::vector<uint8_t> kEmptyVector;
|
||||
EXPECT_EQ(SafeByteIdToString(kEmptyVector), "<empty>");
|
||||
}
|
||||
|
||||
TEST(SafeByteIdToString, AllAlphaNumeric_NoEscape) {
|
||||
const std::string sid("Hello, World!");
|
||||
const std::vector<uint8_t> vid(sid.begin(), sid.end());
|
||||
EXPECT_EQ(SafeByteIdToString(sid), "\"Hello, World!\"");
|
||||
EXPECT_EQ(SafeByteIdToString(vid), "\"Hello, World!\"");
|
||||
}
|
||||
|
||||
TEST(SafeByteIdToString, AllAlphaNumeric_NoEscape_Exhaustive) {
|
||||
for (char ch = 'a'; ch <= 'z'; ch++) {
|
||||
const std::string sid(1, ch);
|
||||
const std::vector<uint8_t> vid(1, ch);
|
||||
std::string expected(1, '"');
|
||||
expected.push_back(ch);
|
||||
expected.push_back('"');
|
||||
EXPECT_EQ(SafeByteIdToString(sid), expected);
|
||||
EXPECT_EQ(SafeByteIdToString(vid), expected);
|
||||
}
|
||||
|
||||
for (char ch = 'A'; ch <= 'Z'; ch++) {
|
||||
const std::string sid(1, ch);
|
||||
const std::vector<uint8_t> vid(1, ch);
|
||||
std::string expected(1, '"');
|
||||
expected.push_back(ch);
|
||||
expected.push_back('"');
|
||||
EXPECT_EQ(SafeByteIdToString(sid), expected);
|
||||
EXPECT_EQ(SafeByteIdToString(vid), expected);
|
||||
}
|
||||
|
||||
for (char ch = '0'; ch <= '9'; ch++) {
|
||||
const std::string sid(1, ch);
|
||||
const std::vector<uint8_t> vid(1, ch);
|
||||
std::string expected(1, '"');
|
||||
expected.push_back(ch);
|
||||
expected.push_back('"');
|
||||
EXPECT_EQ(SafeByteIdToString(sid), expected);
|
||||
EXPECT_EQ(SafeByteIdToString(vid), expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SafeByteIdToString, AllSymbols_NoEscape) {
|
||||
for (char ch = ' '; ch <= '/'; ch++) {
|
||||
if (ch == '"') continue;
|
||||
const std::string sid(1, ch);
|
||||
const std::vector<uint8_t> vid(1, ch);
|
||||
std::string expected(1, '"');
|
||||
expected.push_back(ch);
|
||||
expected.push_back('"');
|
||||
EXPECT_EQ(SafeByteIdToString(sid), expected);
|
||||
EXPECT_EQ(SafeByteIdToString(vid), expected);
|
||||
}
|
||||
|
||||
for (char ch = ':'; ch <= '@'; ch++) {
|
||||
const std::string sid(1, ch);
|
||||
const std::vector<uint8_t> vid(1, ch);
|
||||
std::string expected(1, '"');
|
||||
expected.push_back(ch);
|
||||
expected.push_back('"');
|
||||
EXPECT_EQ(SafeByteIdToString(sid), expected);
|
||||
EXPECT_EQ(SafeByteIdToString(vid), expected);
|
||||
}
|
||||
|
||||
for (char ch = '['; ch <= '`'; ch++) {
|
||||
if (ch == '\\') continue;
|
||||
const std::string sid(1, ch);
|
||||
const std::vector<uint8_t> vid(1, ch);
|
||||
std::string expected(1, '"');
|
||||
expected.push_back(ch);
|
||||
expected.push_back('"');
|
||||
EXPECT_EQ(SafeByteIdToString(sid), expected);
|
||||
EXPECT_EQ(SafeByteIdToString(vid), expected);
|
||||
}
|
||||
|
||||
for (char ch = '{'; ch <= '~'; ch++) {
|
||||
const std::string sid(1, ch);
|
||||
const std::vector<uint8_t> vid(1, ch);
|
||||
std::string expected(1, '"');
|
||||
expected.push_back(ch);
|
||||
expected.push_back('"');
|
||||
EXPECT_EQ(SafeByteIdToString(sid), expected);
|
||||
EXPECT_EQ(SafeByteIdToString(vid), expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SafeByteIdToString, Escapable_NoEscape) {
|
||||
const std::string quote_sid(1, '"');
|
||||
const std::vector<uint8_t> quote_vid(1, '"');
|
||||
EXPECT_EQ(SafeByteIdToString(quote_sid), "\"\\\"\"");
|
||||
EXPECT_EQ(SafeByteIdToString(quote_vid), "\"\\\"\"");
|
||||
|
||||
const std::string backslash_sid(1, '\\');
|
||||
const std::vector<uint8_t> backslash_vid(1, '\\');
|
||||
EXPECT_EQ(SafeByteIdToString(backslash_sid), "\"\\\\\"");
|
||||
EXPECT_EQ(SafeByteIdToString(backslash_vid), "\"\\\\\"");
|
||||
}
|
||||
|
||||
TEST(SafeByteIdToString, AllNonPrintable) {
|
||||
const std::vector<uint8_t> vid = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
const std::string sid(vid.begin(), vid.end());
|
||||
|
||||
EXPECT_EQ(SafeByteIdToString(vid), "00010203040506070809");
|
||||
EXPECT_EQ(SafeByteIdToString(sid), "00010203040506070809");
|
||||
}
|
||||
} // namespace wvutil
|
||||
|
||||
Reference in New Issue
Block a user