OEMCrypto and OPK v19.3

This commit is contained in:
John W. Bruce
2024-09-05 07:21:15 +00:00
parent 482b0923ca
commit 365ea19c9a
95 changed files with 4332 additions and 528 deletions

View File

@@ -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_

View 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_

View File

@@ -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

View File

@@ -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