Restrict uses of BoringSSL.
(This is a merge of http://go/wvgerrit/71883) This moves all the SSL code to privacy_crypto so we can use the iOS-specific versions and not use any BoringSSL. The iOS version doesn't support OEM certificates. Note that the tests still use BoringSSL. Bug: 126559819 Test: build_and_run_all_unit_tests.sh Change-Id: Ib0fad5d95b283b6cd6e02d8a08bcf248c5900bc4
This commit is contained in:
@@ -68,6 +68,23 @@ class RsaPublicKey {
|
|||||||
CORE_DISALLOW_COPY_AND_ASSIGN(RsaPublicKey);
|
CORE_DISALLOW_COPY_AND_ASSIGN(RsaPublicKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts an integer value from the extensions in a certificate.
|
||||||
|
* @param cert A PKCS7 encoded X.509 certificate chain.
|
||||||
|
* @param extension_oid The ID of the extension to get.
|
||||||
|
* @param cert_index The zero-based index of the certificate in the chain to
|
||||||
|
* fetch from.
|
||||||
|
* @param value [OUT] Will contain the extracted value.
|
||||||
|
* @return True on success, false on error.
|
||||||
|
*/
|
||||||
|
bool ExtractExtensionValueFromCertificate(const std::string& cert,
|
||||||
|
const std::string& extension_oid,
|
||||||
|
size_t cert_index, uint32_t* value);
|
||||||
|
|
||||||
|
std::string Md5Hash(const std::string& data);
|
||||||
|
std::string Sha256Hash(const std::string& data);
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // WVCDM_CORE_PRIVACY_CRYPTO_H_
|
#endif // WVCDM_CORE_PRIVACY_CRYPTO_H_
|
||||||
|
|||||||
@@ -16,10 +16,8 @@
|
|||||||
#include "crypto_key.h"
|
#include "crypto_key.h"
|
||||||
#include "entitlement_key_session.h"
|
#include "entitlement_key_session.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "openssl/asn1.h"
|
|
||||||
#include "openssl/sha.h"
|
|
||||||
#include "openssl/x509v3.h"
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
#include "privacy_crypto.h"
|
||||||
#include "properties.h"
|
#include "properties.h"
|
||||||
#include "pst_report.h"
|
#include "pst_report.h"
|
||||||
#include "string_conversions.h"
|
#include "string_conversions.h"
|
||||||
@@ -48,30 +46,8 @@ const size_t kOemCryptoApiVersionSupportsBigUsageTables = 13;
|
|||||||
const size_t kOemCryptoApiVersionSupportsSwitchingCipherMode = 14;
|
const size_t kOemCryptoApiVersionSupportsSwitchingCipherMode = 14;
|
||||||
|
|
||||||
// Constants and utility objects relating to OEM Certificates
|
// Constants and utility objects relating to OEM Certificates
|
||||||
const int kExtensionOidSize = 64;
|
|
||||||
const char* const kWidevineSystemIdExtensionOid = "1.3.6.1.4.1.11129.4.1.1";
|
const char* const kWidevineSystemIdExtensionOid = "1.3.6.1.4.1.11129.4.1.1";
|
||||||
|
|
||||||
// Helpers for working with BoringSSL
|
|
||||||
template <typename T, void (*func)(T*)>
|
|
||||||
class boringssl_ptr {
|
|
||||||
public:
|
|
||||||
explicit boringssl_ptr(T* p = NULL) : ptr_(p) {}
|
|
||||||
~boringssl_ptr() {
|
|
||||||
if (ptr_) func(ptr_);
|
|
||||||
}
|
|
||||||
T& operator*() const { return *ptr_; }
|
|
||||||
T* operator->() const { return ptr_; }
|
|
||||||
T* get() const { return ptr_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
T* ptr_;
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
void DeleteX509Stack(STACK_OF(X509)* stack) {
|
|
||||||
sk_X509_pop_free(stack, X509_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -503,13 +479,7 @@ CdmResponseType CryptoSession::GetExternalDeviceUniqueId(
|
|||||||
pre_provision_token_type_ == kClientTokenOemCert) {
|
pre_provision_token_type_ == kClientTokenOemCert) {
|
||||||
// To keep the size of the value passed back to the application down, hash
|
// To keep the size of the value passed back to the application down, hash
|
||||||
// the large OEM Public Cert to a smaller value.
|
// the large OEM Public Cert to a smaller value.
|
||||||
uint8_t hash[SHA256_DIGEST_LENGTH];
|
temp = Sha256Hash(temp);
|
||||||
SHA256_CTX ctx;
|
|
||||||
SHA256_Init(&ctx);
|
|
||||||
SHA256_Update(&ctx, temp.data(), temp.length());
|
|
||||||
SHA256_Final(hash, &ctx);
|
|
||||||
|
|
||||||
temp.assign(reinterpret_cast<char*>(hash), SHA256_DIGEST_LENGTH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*device_id = temp;
|
*device_id = temp;
|
||||||
@@ -612,103 +582,8 @@ CdmResponseType CryptoSession::GetSystemIdInternal(uint32_t* system_id) {
|
|||||||
|
|
||||||
bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
|
||||||
uint32_t* system_id) {
|
uint32_t* system_id) {
|
||||||
// Load the certificate chain into a BoringSSL X509 Stack
|
return ExtractExtensionValueFromCertificate(
|
||||||
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
oem_cert, kWidevineSystemIdExtensionOid, /* cert_index */ 1, system_id);
|
||||||
sk_X509_new_null());
|
|
||||||
if (x509_stack.get() == NULL) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Unable to allocate X509 Stack.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBS pkcs7;
|
|
||||||
CBS_init(&pkcs7, reinterpret_cast<const uint8_t*>(oem_cert.data()),
|
|
||||||
oem_cert.size());
|
|
||||||
if (!PKCS7_get_certificates(x509_stack.get(), &pkcs7)) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Error getting certificate chain.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
STACK_OF(X509)* certs = x509_stack.get();
|
|
||||||
|
|
||||||
// Get the Widevine intermediate cert from the stack
|
|
||||||
if (sk_X509_num(certs) != 2) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Expected 2 certificates in chain, got %d",
|
|
||||||
sk_X509_num(certs));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
X509* const intermediate_cert = sk_X509_value(certs, 1);
|
|
||||||
if (!intermediate_cert) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Unable to get intermediate cert.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the Widevine System ID extension in the intermediate cert
|
|
||||||
const int extension_count = X509_get_ext_count(intermediate_cert);
|
|
||||||
for (int i = 0; i < extension_count; ++i) {
|
|
||||||
X509_EXTENSION* const extension = X509_get_ext(intermediate_cert, i);
|
|
||||||
if (!extension) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Unable to get cert extension %d", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASN1_OBJECT* const extension_object = X509_EXTENSION_get_object(extension);
|
|
||||||
if (!extension_object) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Unable to get object of cert extension %d", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char extension_name[kExtensionOidSize + 1];
|
|
||||||
OBJ_obj2txt(extension_name, kExtensionOidSize, extension_object, 1);
|
|
||||||
if (strcmp(extension_name, kWidevineSystemIdExtensionOid) != 0) {
|
|
||||||
// This extension is not the Widevine System ID, so we should move on to
|
|
||||||
// the next one.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASN1_OCTET_STRING* const octet_str = X509_EXTENSION_get_data(extension);
|
|
||||||
if (!octet_str) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Unable to get data of Widevine System ID extension.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char* data = octet_str->data;
|
|
||||||
if (!data) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Null data in Widevine System ID extension.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASN1_INTEGER* const asn1_integer =
|
|
||||||
d2i_ASN1_INTEGER(NULL, &data, octet_str->length);
|
|
||||||
if (!asn1_integer) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Unable to decode data in Widevine System ID extension.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const long system_id_long = ASN1_INTEGER_get(asn1_integer);
|
|
||||||
ASN1_INTEGER_free(asn1_integer);
|
|
||||||
if (system_id_long == -1) {
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Unable to decode ASN integer in Widevine System ID extension.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*system_id = static_cast<uint32_t>(system_id_long);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGE("CryptoSession::ExtractSystemIdFromOemCert: "
|
|
||||||
"Widevine System ID extension not found.");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CryptoSession::GetProvisioningId(std::string* provisioning_id) {
|
CdmResponseType CryptoSession::GetProvisioningId(std::string* provisioning_id) {
|
||||||
|
|||||||
@@ -10,21 +10,11 @@
|
|||||||
#include "file_store.h"
|
#include "file_store.h"
|
||||||
#include "license_protocol.pb.h"
|
#include "license_protocol.pb.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "privacy_crypto.h"
|
||||||
#include "properties.h"
|
#include "properties.h"
|
||||||
#include "string_conversions.h"
|
#include "string_conversions.h"
|
||||||
#include "wv_cdm_constants.h"
|
#include "wv_cdm_constants.h"
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <CommonCrypto/CommonDigest.h>
|
|
||||||
#define SHA256 CC_SHA256
|
|
||||||
#define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
|
|
||||||
#define MD5 CC_MD5
|
|
||||||
#define MD5_DIGEST_LENGTH CC_MD5_DIGEST_LENGTH
|
|
||||||
#else
|
|
||||||
#include <openssl/md5.h>
|
|
||||||
#include <openssl/sha.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Protobuf generated classes.
|
// Protobuf generated classes.
|
||||||
using video_widevine_client::sdk::DeviceCertificate;
|
using video_widevine_client::sdk::DeviceCertificate;
|
||||||
using video_widevine_client::sdk::HashedFile;
|
using video_widevine_client::sdk::HashedFile;
|
||||||
@@ -67,17 +57,6 @@ const char kEmptyFileName[] = "";
|
|||||||
const char kUsageTableFileName[] = "usgtable.bin";
|
const char kUsageTableFileName[] = "usgtable.bin";
|
||||||
const char kWildcard[] = "*";
|
const char kWildcard[] = "*";
|
||||||
|
|
||||||
bool Hash(const std::string& data, std::string* hash) {
|
|
||||||
if (!hash) return false;
|
|
||||||
hash->resize(SHA256_DIGEST_LENGTH);
|
|
||||||
|
|
||||||
const unsigned char* input =
|
|
||||||
reinterpret_cast<const unsigned char*>(data.data());
|
|
||||||
unsigned char* output = reinterpret_cast<unsigned char*>(&(*hash)[0]);
|
|
||||||
SHA256(input, data.size(), output);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -1183,12 +1162,7 @@ bool DeviceFiles::DeleteUsageTableInfo() {
|
|||||||
DeviceFiles::ResponseType DeviceFiles::StoreFileWithHash(
|
DeviceFiles::ResponseType DeviceFiles::StoreFileWithHash(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::string& serialized_file) {
|
const std::string& serialized_file) {
|
||||||
// calculate SHA hash
|
std::string hash = Sha256Hash(serialized_file);
|
||||||
std::string hash;
|
|
||||||
if (!Hash(serialized_file, &hash)) {
|
|
||||||
LOGW("DeviceFiles::StoreFileWithHash: Hash computation failed");
|
|
||||||
return kHashComputationFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in hashed file data
|
// Fill in hashed file data
|
||||||
HashedFile hash_file;
|
HashedFile hash_file;
|
||||||
@@ -1296,12 +1270,7 @@ DeviceFiles::ResponseType DeviceFiles::RetrieveHashedFile(
|
|||||||
return kFileParseError1;
|
return kFileParseError1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string hash;
|
std::string hash = Sha256Hash(hash_file.file());
|
||||||
if (!Hash(hash_file.file(), &hash)) {
|
|
||||||
LOGW("DeviceFiles::RetrieveHashedFile: Hash computation failed");
|
|
||||||
return kHashComputationFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash != hash_file.hash()) {
|
if (hash != hash_file.hash()) {
|
||||||
LOGW("DeviceFiles::RetrieveHashedFile: Hash mismatch");
|
LOGW("DeviceFiles::RetrieveHashedFile: Hash mismatch");
|
||||||
// Remove the corrupted file so the caller will not get the same error
|
// Remove the corrupted file so the caller will not get the same error
|
||||||
@@ -1387,11 +1356,9 @@ std::string DeviceFiles::GetUsageInfoFileName(const std::string& app_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string DeviceFiles::GetFileNameSafeHash(const std::string& input) {
|
std::string DeviceFiles::GetFileNameSafeHash(const std::string& input) {
|
||||||
std::vector<uint8_t> hash(MD5_DIGEST_LENGTH);
|
std::string hash = Md5Hash(input);
|
||||||
const unsigned char* input_ptr =
|
return wvcdm::Base64SafeEncode(
|
||||||
reinterpret_cast<const unsigned char*>(input.data());
|
std::vector<uint8_t>(hash.begin(), hash.end()));
|
||||||
MD5(input_ptr, input.size(), &hash[0]);
|
|
||||||
return wvcdm::Base64SafeEncode(hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
@@ -10,12 +10,15 @@
|
|||||||
#include "privacy_crypto.h"
|
#include "privacy_crypto.h"
|
||||||
|
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
|
#include <openssl/asn1.h>
|
||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/md5.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
@@ -49,6 +52,38 @@ void FreeKey(RSA* key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, void (*func)(T*)>
|
||||||
|
class boringssl_ptr {
|
||||||
|
public:
|
||||||
|
explicit boringssl_ptr(T* p = NULL) : ptr_(p) {}
|
||||||
|
~boringssl_ptr() {
|
||||||
|
if (ptr_) func(ptr_);
|
||||||
|
}
|
||||||
|
T& operator*() const { return *ptr_; }
|
||||||
|
T* operator->() const { return ptr_; }
|
||||||
|
T* get() const { return ptr_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* ptr_;
|
||||||
|
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
void DeleteX509Stack(STACK_OF(X509)* stack) {
|
||||||
|
sk_X509_pop_free(stack, X509_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetExtensionOid(X509_EXTENSION* extension) {
|
||||||
|
ASN1_OBJECT* const extension_object = X509_EXTENSION_get_object(extension);
|
||||||
|
if (!extension_object) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const int size = OBJ_obj2txt(nullptr, 0, extension_object, 1);
|
||||||
|
std::string ret(size, '\0');
|
||||||
|
OBJ_obj2txt(&ret[0], ret.size() + 1, extension_object, 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -287,4 +322,110 @@ bool RsaPublicKey::VerifySignature(const std::string& message,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ExtractExtensionValueFromCertificate(const std::string& cert,
|
||||||
|
const std::string& extension_oid,
|
||||||
|
size_t cert_index, uint32_t* value) {
|
||||||
|
// Load the certificate chain into a BoringSSL X509 Stack
|
||||||
|
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||||
|
sk_X509_new_null());
|
||||||
|
if (x509_stack.get() == NULL) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Unable to allocate X509 Stack.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBS pkcs7;
|
||||||
|
CBS_init(&pkcs7, reinterpret_cast<const uint8_t*>(cert.data()), cert.size());
|
||||||
|
if (!PKCS7_get_certificates(x509_stack.get(), &pkcs7)) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Error getting certificate chain.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
STACK_OF(X509)* certs = x509_stack.get();
|
||||||
|
|
||||||
|
// Find the desired certificate from the stack.
|
||||||
|
if (sk_X509_num(certs) <= cert_index) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Expected at least %zu certificates in chain, got %d",
|
||||||
|
cert_index + 1, sk_X509_num(certs));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509* const intermediate_cert = sk_X509_value(certs, cert_index);
|
||||||
|
if (!intermediate_cert) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Unable to get intermediate cert.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the Widevine System ID extension in the intermediate cert
|
||||||
|
const int extension_count = X509_get_ext_count(intermediate_cert);
|
||||||
|
for (int i = 0; i < extension_count; ++i) {
|
||||||
|
X509_EXTENSION* const extension = X509_get_ext(intermediate_cert, i);
|
||||||
|
if (!extension) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Unable to get cert extension %d", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetExtensionOid(extension) != extension_oid) {
|
||||||
|
// This extension is not the Widevine System ID, so we should move on to
|
||||||
|
// the next one.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASN1_OCTET_STRING* const octet_str = X509_EXTENSION_get_data(extension);
|
||||||
|
if (!octet_str) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Unable to get data of extension.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char* data = octet_str->data;
|
||||||
|
if (!data) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Null data in extension.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASN1_INTEGER* const asn1_integer =
|
||||||
|
d2i_ASN1_INTEGER(NULL, &data, octet_str->length);
|
||||||
|
if (!asn1_integer) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Unable to decode data in extension.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const long system_id_long = ASN1_INTEGER_get(asn1_integer);
|
||||||
|
ASN1_INTEGER_free(asn1_integer);
|
||||||
|
if (system_id_long == -1) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: "
|
||||||
|
"Unable to decode ASN integer in extension.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = static_cast<uint32_t>(system_id_long);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: Extension not found.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Md5Hash(const std::string& data) {
|
||||||
|
std::string hash(MD5_DIGEST_LENGTH, '\0');
|
||||||
|
MD5(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||||
|
reinterpret_cast<uint8_t*>(&hash[0]));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Sha256Hash(const std::string& data) {
|
||||||
|
std::string hash(SHA256_DIGEST_LENGTH, '\0');
|
||||||
|
SHA256(reinterpret_cast<const uint8_t*>(data.data()), data.size(),
|
||||||
|
reinterpret_cast<uint8_t*>(&hash[0]));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
@@ -9,6 +9,18 @@
|
|||||||
|
|
||||||
#include "privacy_crypto.h"
|
#include "privacy_crypto.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
# include <CommonCrypto/CommonDigest.h>
|
||||||
|
# define SHA256 CC_SHA256
|
||||||
|
# define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
|
||||||
|
# define MD5 CC_MD5
|
||||||
|
# define MD5_DIGEST_LENGTH CC_MD5_DIGEST_LENGTH
|
||||||
|
#else
|
||||||
|
# error "No hash algorithm known for this platform."
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
AesCbcKey::AesCbcKey() {}
|
AesCbcKey::AesCbcKey() {}
|
||||||
@@ -38,4 +50,24 @@ bool RsaPublicKey::VerifySignature(const std::string& message,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ExtractExtensionValueFromCertificate(const std::string& cert,
|
||||||
|
const std::string& extension_oid,
|
||||||
|
size_t cert_index, uint32_t* value) {
|
||||||
|
LOGE("ExtractExtensionValueFromCertificate: Not supported in this build.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Md5Hash(const std::string& data) {
|
||||||
|
std::string hash(MD5_DIGEST_LENGTH, '\0');
|
||||||
|
MD5(data.data(), data.size(), reinterpret_cast<uint8_t*>(&hash[0]));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Sha256Hash(const std::string& data) {
|
||||||
|
std::string hash(SHA256_DIGEST_LENGTH, '\0');
|
||||||
|
SHA256(data.data(), data.size(), reinterpret_cast<uint8_t*>(&hash[0]));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
Reference in New Issue
Block a user