зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1530481 - Refactor PrioEncoder to be usable from C++. r=rhelmer
For some reason Telemetry's gtests doesn't like one or more of the dependencies of mprio.h, so I had to move it into PrioEncoder's cpp and forward declare the PublicKey typedefs. It isn't the cleanest, but I'm surprised C++ let me off with just that level of nonsensery. Differential Revision: https://phabricator.services.mozilla.com/D22605 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a100616355
Коммит
799c96cf89
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
|
||||
#include "mprio.h"
|
||||
|
||||
#include "PrioEncoder.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -50,113 +52,32 @@ void PrioEncoder::Encode(GlobalObject& aGlobal, const nsCString& aBatchID,
|
|||
return;
|
||||
}
|
||||
|
||||
SECStatus prio_rv = SECSuccess;
|
||||
|
||||
if (!sSingleton) {
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCStringN<CURVE25519_KEY_LEN_HEX + 1> prioKeyA;
|
||||
rv = Preferences::GetCString("prio.publicKeyA", prioKeyA);
|
||||
nsCString aResult;
|
||||
nsCString bResult;
|
||||
nsresult rv = PrioEncoder::EncodeNative(aBatchID, aPrioParams.mBooleans,
|
||||
aResult, bResult);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCStringN<CURVE25519_KEY_LEN_HEX + 1> prioKeyB;
|
||||
rv = Preferences::GetCString("prio.publicKeyB", prioKeyB);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that both public keys are of the right length
|
||||
// and contain only hex digits 0-9a-fA-f
|
||||
if (!PrioEncoder::IsValidHexPublicKey(prioKeyA) ||
|
||||
!PrioEncoder::IsValidHexPublicKey(prioKeyB)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
prio_rv = Prio_init();
|
||||
|
||||
if (prio_rv != SECSuccess) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
prio_rv = PublicKey_import_hex(
|
||||
&sPublicKeyA,
|
||||
reinterpret_cast<const unsigned char*>(prioKeyA.BeginReading()),
|
||||
CURVE25519_KEY_LEN_HEX);
|
||||
if (prio_rv != SECSuccess) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
prio_rv = PublicKey_import_hex(
|
||||
&sPublicKeyB,
|
||||
reinterpret_cast<const unsigned char*>(prioKeyB.BeginReading()),
|
||||
CURVE25519_KEY_LEN_HEX);
|
||||
if (prio_rv != SECSuccess) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
sSingleton = new PrioEncoder();
|
||||
ClearOnShutdown(&sSingleton);
|
||||
}
|
||||
|
||||
nsTArray<bool> dataItems = aPrioParams.mBooleans;
|
||||
if (dataItems.Length() > gNumBooleans) {
|
||||
aRv.ThrowRangeError<MSG_VALUE_OUT_OF_RANGE>(
|
||||
NS_LITERAL_STRING("Maximum boolean value exceeded"));
|
||||
return;
|
||||
}
|
||||
|
||||
PrioConfig prioConfig = PrioConfig_new(
|
||||
dataItems.Length(), sPublicKeyA, sPublicKeyB,
|
||||
reinterpret_cast<const unsigned char*>(aBatchID.BeginReading()),
|
||||
aBatchID.Length());
|
||||
|
||||
if (!prioConfig) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
auto configGuard = MakeScopeExit([&] { PrioConfig_clear(prioConfig); });
|
||||
|
||||
unsigned char* forServerA = nullptr;
|
||||
unsigned int lenA = 0;
|
||||
unsigned char* forServerB = nullptr;
|
||||
unsigned int lenB = 0;
|
||||
|
||||
prio_rv = PrioClient_encode(prioConfig, dataItems.Elements(), &forServerA,
|
||||
&lenA, &forServerB, &lenB);
|
||||
|
||||
nsTArray<uint8_t> arrayForServerA;
|
||||
nsTArray<uint8_t> arrayForServerB;
|
||||
|
||||
if (!arrayForServerA.AppendElements(reinterpret_cast<uint8_t*>(forServerA),
|
||||
lenA, fallible)) {
|
||||
if (!arrayForServerA.AppendElements(
|
||||
reinterpret_cast<const uint8_t*>(aResult.BeginReading()),
|
||||
aResult.Length(), fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
free(forServerA);
|
||||
|
||||
if (!arrayForServerB.AppendElements(reinterpret_cast<uint8_t*>(forServerB),
|
||||
lenB, fallible)) {
|
||||
if (!arrayForServerB.AppendElements(
|
||||
reinterpret_cast<const uint8_t*>(bResult.BeginReading()),
|
||||
bResult.Length(), fallible)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
free(forServerB);
|
||||
|
||||
if (prio_rv != SECSuccess) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> valueA(aGlobal.Context());
|
||||
if (!ToJSValue(aGlobal.Context(),
|
||||
TypedArrayCreator<Uint8Array>(arrayForServerA), &valueA)) {
|
||||
|
@ -176,6 +97,49 @@ void PrioEncoder::Encode(GlobalObject& aGlobal, const nsCString& aBatchID,
|
|||
aData.mB.Construct().Init(&valueB.toObject());
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult PrioEncoder::EncodeNative(const nsCString& aBatchID,
|
||||
const nsTArray<bool>& aData,
|
||||
nsCString& aResult, nsCString& bResult) {
|
||||
SECStatus prio_rv = SECSuccess;
|
||||
|
||||
nsresult rv = PrioEncoder::LazyInitSingleton();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aData.Length() > gNumBooleans) {
|
||||
return NS_ERROR_RANGE_ERR;
|
||||
}
|
||||
|
||||
PrioConfig prioConfig = PrioConfig_new(
|
||||
aData.Length(), sPublicKeyA, sPublicKeyB,
|
||||
reinterpret_cast<const unsigned char*>(aBatchID.BeginReading()),
|
||||
aBatchID.Length());
|
||||
|
||||
if (!prioConfig) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
auto configGuard = MakeScopeExit([&] { PrioConfig_clear(prioConfig); });
|
||||
|
||||
unsigned char* forServerA = nullptr;
|
||||
unsigned int lenA = 0;
|
||||
unsigned char* forServerB = nullptr;
|
||||
unsigned int lenB = 0;
|
||||
|
||||
prio_rv = PrioClient_encode(prioConfig, aData.Elements(), &forServerA, &lenA,
|
||||
&forServerB, &lenB);
|
||||
|
||||
aResult.Adopt(reinterpret_cast<char*>(forServerA), lenA);
|
||||
bResult.Adopt(reinterpret_cast<char*>(forServerB), lenB);
|
||||
|
||||
if (prio_rv != SECSuccess) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool PrioEncoder::IsValidHexPublicKey(mozilla::Span<const char> aStr) {
|
||||
if (aStr.Length() != CURVE25519_KEY_LEN_HEX) {
|
||||
return false;
|
||||
|
@ -190,5 +154,58 @@ bool PrioEncoder::IsValidHexPublicKey(mozilla::Span<const char> aStr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult PrioEncoder::LazyInitSingleton() {
|
||||
if (!sSingleton) {
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCStringN<CURVE25519_KEY_LEN_HEX + 1> prioKeyA;
|
||||
rv = Preferences::GetCString("prio.publicKeyA", prioKeyA);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCStringN<CURVE25519_KEY_LEN_HEX + 1> prioKeyB;
|
||||
rv = Preferences::GetCString("prio.publicKeyB", prioKeyB);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Check that both public keys are of the right length
|
||||
// and contain only hex digits 0-9a-fA-f
|
||||
if (!PrioEncoder::IsValidHexPublicKey(prioKeyA) ||
|
||||
!PrioEncoder::IsValidHexPublicKey(prioKeyB)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
SECStatus prio_rv = SECSuccess;
|
||||
prio_rv = Prio_init();
|
||||
|
||||
if (prio_rv != SECSuccess) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
prio_rv = PublicKey_import_hex(
|
||||
&sPublicKeyA,
|
||||
reinterpret_cast<const unsigned char*>(prioKeyA.BeginReading()),
|
||||
CURVE25519_KEY_LEN_HEX);
|
||||
if (prio_rv != SECSuccess) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
prio_rv = PublicKey_import_hex(
|
||||
&sPublicKeyB,
|
||||
reinterpret_cast<const unsigned char*>(prioKeyB.BeginReading()),
|
||||
CURVE25519_KEY_LEN_HEX);
|
||||
if (prio_rv != SECSuccess) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
sSingleton = new PrioEncoder();
|
||||
ClearOnShutdown(&sSingleton);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#include "mozilla/dom/PrioEncoderBinding.h"
|
||||
#include "mozilla/dom/RootedDictionary.h"
|
||||
|
||||
#include "mprio.h"
|
||||
|
||||
class nsIGlobalObject;
|
||||
typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
|
||||
typedef SECKEYPublicKey* PublicKey;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -21,6 +21,12 @@ class PrioEncoder {
|
|||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(PrioEncoder)
|
||||
|
||||
// C++ API
|
||||
static nsresult EncodeNative(const nsCString& aBatchID,
|
||||
const nsTArray<bool>& aData, nsCString& aResult,
|
||||
nsCString& bResult);
|
||||
|
||||
// DOM API
|
||||
static void Encode(GlobalObject& aGlobal, const nsCString& aBatchID,
|
||||
const PrioParams& aPrioParams,
|
||||
RootedDictionary<PrioEncodedData>& aData,
|
||||
|
@ -40,6 +46,8 @@ class PrioEncoder {
|
|||
static StaticRefPtr<PrioEncoder> sSingleton;
|
||||
|
||||
static bool IsValidHexPublicKey(mozilla::Span<const char>);
|
||||
|
||||
static nsresult LazyInitSingleton();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
#include "mprio.h"
|
||||
|
||||
TEST(PrioEncoder, BadPublicKeys) {
|
||||
mozilla::dom::AutoJSAPI jsAPI;
|
||||
ASSERT_TRUE(jsAPI.Init(xpc::PrivilegedJunkScope()));
|
||||
|
|
Загрузка…
Ссылка в новой задаче