зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1684040 - P3: Encrypt and decrypt DNS packet r=necko-reviewers,kjacobs,valentin
Differential Revision: https://phabricator.services.mozilla.com/D101684
This commit is contained in:
Родитель
715197de42
Коммит
119a94bbef
|
@ -151,6 +151,13 @@ union NetAddr {
|
|||
bool ToStringBuffer(char* buf, uint32_t bufSize) const;
|
||||
};
|
||||
|
||||
#define ODOH_VERSION 0xff03
|
||||
static const char kODoHQuery[] = "odoh query";
|
||||
static const char hODoHConfigID[] = "odoh key id";
|
||||
static const char kODoHSecret[] = "odoh secret";
|
||||
static const char kODoHKey[] = "odoh key";
|
||||
static const char kODoHNonce[] = "odoh nonce";
|
||||
|
||||
struct ObliviousDoHConfigContents {
|
||||
uint16_t mKemId;
|
||||
uint16_t mKdfId;
|
||||
|
@ -165,6 +172,17 @@ struct ObliviousDoHConfig {
|
|||
nsTArray<uint8_t> mConfigId;
|
||||
};
|
||||
|
||||
enum ObliviousDoHMessageType : uint8_t {
|
||||
ODOH_QUERY = 1,
|
||||
ODOH_RESPONSE = 2,
|
||||
};
|
||||
|
||||
struct ObliviousDoHMessage {
|
||||
ObliviousDoHMessageType mType;
|
||||
nsTArray<uint8_t> mKeyId;
|
||||
nsTArray<uint8_t> mEncryptedMessage;
|
||||
};
|
||||
|
||||
class AddrInfo {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AddrInfo)
|
||||
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
#include "DNSPacket.h"
|
||||
|
||||
#include "DNS.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "ODoHService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
|
@ -981,6 +986,78 @@ nsresult DNSPacket::Decode(
|
|||
mBodySize);
|
||||
}
|
||||
|
||||
static SECItem* CreateRawConfig(const ObliviousDoHConfig& aConfig) {
|
||||
SECItem* item(::SECITEM_AllocItem(nullptr, nullptr,
|
||||
8 + aConfig.mContents.mPublicKey.Length()));
|
||||
if (!item) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint16_t index = 0;
|
||||
NetworkEndian::writeUint16(&item->data[index], aConfig.mContents.mKemId);
|
||||
index += 2;
|
||||
NetworkEndian::writeUint16(&item->data[index], aConfig.mContents.mKdfId);
|
||||
index += 2;
|
||||
NetworkEndian::writeUint16(&item->data[index], aConfig.mContents.mAeadId);
|
||||
index += 2;
|
||||
uint16_t keyLength = aConfig.mContents.mPublicKey.Length();
|
||||
NetworkEndian::writeUint16(&item->data[index], keyLength);
|
||||
index += 2;
|
||||
memcpy(&item->data[index], aConfig.mContents.mPublicKey.Elements(),
|
||||
aConfig.mContents.mPublicKey.Length());
|
||||
return item;
|
||||
}
|
||||
|
||||
static bool CreateConfigId(ObliviousDoHConfig& aConfig) {
|
||||
SECStatus rv;
|
||||
CK_HKDF_PARAMS params = {0};
|
||||
SECItem paramsi = {siBuffer, (unsigned char*)¶ms, sizeof(params)};
|
||||
|
||||
UniquePK11SlotInfo slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UniqueSECItem rawConfig(CreateRawConfig(aConfig));
|
||||
if (!rawConfig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UniquePK11SymKey configKey(PK11_ImportDataKey(slot.get(), CKM_HKDF_DATA,
|
||||
PK11_OriginUnwrap, CKA_DERIVE,
|
||||
rawConfig.get(), NULL));
|
||||
if (!configKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
params.bExtract = CK_TRUE;
|
||||
params.bExpand = CK_TRUE;
|
||||
params.prfHashMechanism = CKM_SHA256;
|
||||
params.ulSaltType = CKF_HKDF_SALT_NULL;
|
||||
params.pInfo = (unsigned char*)&hODoHConfigID[0];
|
||||
params.ulInfoLen = strlen(hODoHConfigID);
|
||||
UniquePK11SymKey derived(PK11_DeriveWithFlags(
|
||||
configKey.get(), CKM_HKDF_DATA, ¶msi, CKM_HKDF_DERIVE, CKA_DERIVE,
|
||||
SHA256_LENGTH, CKF_SIGN | CKF_VERIFY));
|
||||
|
||||
rv = PK11_ExtractKeyValue(derived.get());
|
||||
if (rv != SECSuccess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SECItem* derivedItem = PK11_GetKeyData(derived.get());
|
||||
if (!derivedItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (derivedItem->len != SHA256_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aConfig.mConfigId.AppendElements(derivedItem->data, derivedItem->len);
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool ODoHDNSPacket::ParseODoHConfigs(const nsCString& aRawODoHConfig,
|
||||
nsTArray<ObliviousDoHConfig>& aOut) {
|
||||
|
@ -1001,24 +1078,421 @@ bool ODoHDNSPacket::ParseODoHConfigs(const nsCString& aRawODoHConfig,
|
|||
//
|
||||
// ObliviousDoHConfig ObliviousDoHConfigs<1..2^16-1>;
|
||||
|
||||
// TODO
|
||||
return false;
|
||||
// At least we need two bytes to indicate the total length of ODoHConfig.
|
||||
if (aRawODoHConfig.Length() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned char* data =
|
||||
reinterpret_cast<const unsigned char*>(aRawODoHConfig.BeginReading());
|
||||
|
||||
uint32_t index = 0;
|
||||
uint16_t length = get16bit(data, index);
|
||||
index += 2;
|
||||
|
||||
if (length != aRawODoHConfig.Length() - 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<ObliviousDoHConfig> result;
|
||||
while (length > 0) {
|
||||
ObliviousDoHConfig config;
|
||||
config.mVersion = get16bit(data, index);
|
||||
index += 2;
|
||||
length -= 2;
|
||||
|
||||
config.mLength = get16bit(data, index);
|
||||
index += 2;
|
||||
length -= 2;
|
||||
|
||||
if (config.mLength > length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
config.mContents.mKemId = get16bit(data, index);
|
||||
index += 2;
|
||||
length -= 2;
|
||||
config.mContents.mKdfId = get16bit(data, index);
|
||||
index += 2;
|
||||
length -= 2;
|
||||
config.mContents.mAeadId = get16bit(data, index);
|
||||
index += 2;
|
||||
length -= 2;
|
||||
|
||||
uint16_t keyLength = get16bit(data, index);
|
||||
index += 2;
|
||||
length -= 2;
|
||||
if (keyLength > length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
config.mContents.mPublicKey.AppendElements(Span(data + index, keyLength));
|
||||
index += keyLength;
|
||||
length -= keyLength;
|
||||
|
||||
CreateConfigId(config);
|
||||
|
||||
// Check if the version of the config is supported and validate its content.
|
||||
if (config.mVersion == ODOH_VERSION &&
|
||||
PK11_HPKE_ValidateParameters(
|
||||
static_cast<HpkeKemId>(config.mContents.mKemId),
|
||||
static_cast<HpkeKdfId>(config.mContents.mKdfId),
|
||||
static_cast<HpkeAeadId>(config.mContents.mAeadId)) == SECSuccess) {
|
||||
result.AppendElement(std::move(config));
|
||||
}
|
||||
}
|
||||
|
||||
aOut = std::move(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
ODoHDNSPacket::~ODoHDNSPacket() {}
|
||||
ODoHDNSPacket::~ODoHDNSPacket() { PK11_HPKE_DestroyContext(mContext, true); }
|
||||
|
||||
nsresult ODoHDNSPacket::EncodeRequest(nsCString& aBody, const nsACString& aHost,
|
||||
uint16_t aType, bool aDisableECS) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsAutoCString queryBody;
|
||||
nsresult rv = DNSPacket::EncodeRequest(queryBody, aHost, aType, aDisableECS);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!gODoHService->ODoHConfigs() || gODoHService->ODoHConfigs()->IsEmpty()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// We only use the first ODoHConfig.
|
||||
const ObliviousDoHConfig& config = (*gODoHService->ODoHConfigs())[0];
|
||||
|
||||
ObliviousDoHMessage message;
|
||||
if (!EncryptDNSQuery(queryBody, 2, config, message)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aBody.Truncate();
|
||||
aBody += message.mType;
|
||||
uint16_t keyIdLength = message.mKeyId.Length();
|
||||
aBody += static_cast<uint8_t>(keyIdLength >> 8);
|
||||
aBody += static_cast<uint8_t>(keyIdLength);
|
||||
aBody.Append(reinterpret_cast<const char*>(message.mKeyId.Elements()),
|
||||
keyIdLength);
|
||||
uint16_t messageLen = message.mEncryptedMessage.Length();
|
||||
aBody += static_cast<uint8_t>(messageLen >> 8);
|
||||
aBody += static_cast<uint8_t>(messageLen);
|
||||
aBody.Append(
|
||||
reinterpret_cast<const char*>(message.mEncryptedMessage.Elements()),
|
||||
messageLen);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* def encrypt_query_body(pkR, key_id, Q_plain):
|
||||
* enc, context = SetupBaseS(pkR, "odoh query")
|
||||
* aad = 0x01 || len(key_id) || key_id
|
||||
* ct = context.Seal(aad, Q_plain)
|
||||
* Q_encrypted = enc || ct
|
||||
* return Q_encrypted
|
||||
*/
|
||||
bool ODoHDNSPacket::EncryptDNSQuery(const nsACString& aQuery,
|
||||
uint16_t aPaddingLen,
|
||||
const ObliviousDoHConfig& aConfig,
|
||||
ObliviousDoHMessage& aOut) {
|
||||
mContext = PK11_HPKE_NewContext(
|
||||
static_cast<HpkeKemId>(aConfig.mContents.mKemId),
|
||||
static_cast<HpkeKdfId>(aConfig.mContents.mKdfId),
|
||||
static_cast<HpkeAeadId>(aConfig.mContents.mAeadId), nullptr, nullptr);
|
||||
if (!mContext) {
|
||||
LOG(("ODoHDNSPacket::EncryptDNSQuery create context failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
SECKEYPublicKey* pkR;
|
||||
SECStatus rv =
|
||||
PK11_HPKE_Deserialize(mContext, aConfig.mContents.mPublicKey.Elements(),
|
||||
aConfig.mContents.mPublicKey.Length(), &pkR);
|
||||
if (rv != SECSuccess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UniqueSECItem hpkeInfo(
|
||||
::SECITEM_AllocItem(nullptr, nullptr, strlen(kODoHQuery)));
|
||||
if (!hpkeInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(hpkeInfo->data, kODoHQuery, strlen(kODoHQuery));
|
||||
|
||||
rv = PK11_HPKE_SetupS(mContext, nullptr, nullptr, pkR, hpkeInfo.get());
|
||||
if (rv != SECSuccess) {
|
||||
LOG(("ODoHDNSPacket::EncryptDNSQuery setupS failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
const SECItem* hpkeEnc = PK11_HPKE_GetEncapPubKey(mContext);
|
||||
if (!hpkeEnc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// aad = 0x01 || len(key_id) || key_id
|
||||
UniqueSECItem aad(::SECITEM_AllocItem(nullptr, nullptr,
|
||||
1 + 2 + aConfig.mConfigId.Length()));
|
||||
if (!aad) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aad->data[0] = ODOH_QUERY;
|
||||
NetworkEndian::writeUint16(&aad->data[1], aConfig.mConfigId.Length());
|
||||
memcpy(&aad->data[3], aConfig.mConfigId.Elements(),
|
||||
aConfig.mConfigId.Length());
|
||||
|
||||
// struct {
|
||||
// opaque dns_message<1..2^16-1>;
|
||||
// opaque padding<0..2^16-1>;
|
||||
// } ObliviousDoHMessagePlaintext;
|
||||
SECItem* odohPlainText(::SECITEM_AllocItem(
|
||||
nullptr, nullptr, 2 + aQuery.Length() + 2 + aPaddingLen));
|
||||
if (!odohPlainText) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mPlainQuery.reset(odohPlainText);
|
||||
memset(mPlainQuery->data, 0, mPlainQuery->len);
|
||||
NetworkEndian::writeUint16(&mPlainQuery->data[0], aQuery.Length());
|
||||
memcpy(&mPlainQuery->data[2], aQuery.BeginReading(), aQuery.Length());
|
||||
NetworkEndian::writeUint16(&mPlainQuery->data[2 + aQuery.Length()],
|
||||
aPaddingLen);
|
||||
|
||||
SECItem* chCt = nullptr;
|
||||
rv = PK11_HPKE_Seal(mContext, aad.get(), mPlainQuery.get(), &chCt);
|
||||
if (rv != SECSuccess) {
|
||||
LOG(("ODoHDNSPacket::EncryptDNSQuery seal failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
UniqueSECItem ct(chCt);
|
||||
|
||||
aOut.mType = ODOH_QUERY;
|
||||
aOut.mKeyId.AppendElements(aConfig.mConfigId);
|
||||
aOut.mEncryptedMessage.AppendElements(Span(hpkeEnc->data, hpkeEnc->len));
|
||||
aOut.mEncryptedMessage.AppendElements(Span(ct->data, ct->len));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult ODoHDNSPacket::Decode(
|
||||
nsCString& aHost, enum TrrType aType, nsCString& aCname, bool aAllowRFC1918,
|
||||
nsHostRecord::TRRSkippedReason& reason, DOHresp& aResp,
|
||||
nsHostRecord::TRRSkippedReason& aReason, DOHresp& aResp,
|
||||
TypeRecordResultType& aTypeResult,
|
||||
nsClassHashtable<nsCStringHashKey, DOHresp>& aAdditionalRecords,
|
||||
uint32_t& aTTL) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (!DecryptDNSResponse()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint32_t index = 0;
|
||||
uint16_t responseLength = get16bit(mResponse, index);
|
||||
index += 2;
|
||||
|
||||
if (mBodySize < (index + responseLength)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
unsigned char* plainResponse = &mResponse[index];
|
||||
index += responseLength;
|
||||
|
||||
uint16_t paddingLen = get16bit(mResponse, index);
|
||||
|
||||
if (static_cast<unsigned int>(4 + responseLength + paddingLen) != mBodySize) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
return DecodeInternal(aHost, aType, aCname, aAllowRFC1918, aReason, aResp,
|
||||
aTypeResult, aAdditionalRecords, aTTL, plainResponse,
|
||||
responseLength);
|
||||
}
|
||||
|
||||
static bool CreateObliviousDoHMessage(const unsigned char* aData,
|
||||
unsigned int aLength,
|
||||
ObliviousDoHMessage& aOut) {
|
||||
if (aLength < 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int index = 0;
|
||||
aOut.mType = static_cast<ObliviousDoHMessageType>(aData[index++]);
|
||||
|
||||
uint16_t keyIdLength = get16bit(aData, index);
|
||||
index += 2;
|
||||
if (aLength < (index + keyIdLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOut.mKeyId.AppendElements(Span(aData + index, keyIdLength));
|
||||
index += keyIdLength;
|
||||
|
||||
uint16_t messageLen = get16bit(aData, index);
|
||||
index += 2;
|
||||
if (aLength < (index + messageLen)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOut.mEncryptedMessage.AppendElements(Span(aData + index, messageLen));
|
||||
return true;
|
||||
}
|
||||
|
||||
static SECStatus HKDFExtract(SECItem* aSalt, PK11SymKey* aIkm,
|
||||
UniquePK11SymKey& aOutKey) {
|
||||
CK_HKDF_PARAMS params = {0};
|
||||
SECItem paramsItem = {siBuffer, (unsigned char*)¶ms, sizeof(params)};
|
||||
|
||||
params.bExtract = CK_TRUE;
|
||||
params.bExpand = CK_FALSE;
|
||||
params.prfHashMechanism = CKM_SHA256;
|
||||
params.ulSaltType = aSalt ? CKF_HKDF_SALT_DATA : CKF_HKDF_SALT_NULL;
|
||||
params.pSalt = aSalt ? (CK_BYTE_PTR)aSalt->data : NULL;
|
||||
params.ulSaltLen = aSalt ? aSalt->len : 0;
|
||||
|
||||
UniquePK11SymKey prk(PK11_Derive(aIkm, CKM_HKDF_DERIVE, ¶msItem,
|
||||
CKM_HKDF_DERIVE, CKA_DERIVE, 0));
|
||||
if (!prk) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
aOutKey.swap(prk);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus HKDFExpand(PK11SymKey* aPrk, const SECItem* aInfo,
|
||||
unsigned int aLen, bool aKey,
|
||||
UniquePK11SymKey& aOutKey) {
|
||||
CK_HKDF_PARAMS params = {0};
|
||||
SECItem paramsItem = {siBuffer, (unsigned char*)¶ms, sizeof(params)};
|
||||
|
||||
params.bExtract = CK_FALSE;
|
||||
params.bExpand = CK_TRUE;
|
||||
params.prfHashMechanism = CKM_SHA256;
|
||||
params.ulSaltType = CKF_HKDF_SALT_NULL;
|
||||
params.pInfo = (CK_BYTE_PTR)aInfo->data;
|
||||
params.ulInfoLen = aInfo->len;
|
||||
CK_MECHANISM_TYPE deriveMech = CKM_HKDF_DERIVE;
|
||||
CK_MECHANISM_TYPE keyMech = aKey ? CKM_AES_GCM : CKM_HKDF_DERIVE;
|
||||
|
||||
UniquePK11SymKey derivedKey(
|
||||
PK11_Derive(aPrk, deriveMech, ¶msItem, keyMech, CKA_DERIVE, aLen));
|
||||
if (!derivedKey) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
aOutKey.swap(derivedKey);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* def decrypt_response_body(context, Q_plain, R_encrypted):
|
||||
* key, nonce = derive_secrets(context, Q_plain)
|
||||
* aad = 0x02 || 0x0000 // 0x0000 represents a 0-length KeyId
|
||||
* R_plain, error = Open(key, nonce, aad, R_encrypted)
|
||||
* return R_plain, error
|
||||
*/
|
||||
bool ODoHDNSPacket::DecryptDNSResponse() {
|
||||
ObliviousDoHMessage message;
|
||||
if (!CreateObliviousDoHMessage(mResponse, mBodySize, message)) {
|
||||
LOG(("ODoHDNSPacket::DecryptDNSResponse invalid responce"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message.mType != ODOH_RESPONSE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// KeyID for response should be empty.
|
||||
if (!message.mKeyId.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// def derive_secrets(context, Q_plain):
|
||||
// odoh_secret = context.Export("odoh secret", 32)
|
||||
// odoh_prk = Extract(Q_plain, odoh_secret)
|
||||
// key = Expand(odoh_prk, "odoh key", Nk)
|
||||
// nonce = Expand(odoh_prk, "odoh nonce", Nn)
|
||||
// return key, nonce
|
||||
const SECItem kODoHSecretInfoItem = {
|
||||
siBuffer, (unsigned char*)kODoHSecret,
|
||||
static_cast<unsigned int>(strlen(kODoHSecret))};
|
||||
const unsigned int kAes128GcmKeyLen = 16;
|
||||
const unsigned int kAes128GcmNonceLen = 12;
|
||||
PK11SymKey* tmp = nullptr;
|
||||
SECStatus rv =
|
||||
PK11_HPKE_ExportSecret(mContext, &kODoHSecretInfoItem, 32, &tmp);
|
||||
if (rv != SECSuccess) {
|
||||
LOG(("ODoHDNSPacket::DecryptDNSResponse export secret failed"));
|
||||
return false;
|
||||
}
|
||||
UniquePK11SymKey odohSecret(tmp);
|
||||
|
||||
SECItem* salt(::SECITEM_AllocItem(nullptr, nullptr, mPlainQuery->len));
|
||||
memcpy(salt->data, mPlainQuery->data, mPlainQuery->len);
|
||||
UniqueSECItem st(salt);
|
||||
UniquePK11SymKey odohPrk;
|
||||
rv = HKDFExtract(salt, odohSecret.get(), odohPrk);
|
||||
if (rv != SECSuccess) {
|
||||
LOG(("ODoHDNSPacket::DecryptDNSResponse extract failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
SECItem keyInfoItem = {siBuffer, (unsigned char*)&kODoHKey[0],
|
||||
static_cast<unsigned int>(strlen(kODoHKey))};
|
||||
UniquePK11SymKey key;
|
||||
rv = HKDFExpand(odohPrk.get(), &keyInfoItem, kAes128GcmKeyLen, true, key);
|
||||
if (rv != SECSuccess) {
|
||||
LOG(("ODoHDNSPacket::DecryptDNSResponse expand key failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
SECItem nonceInfoItem = {siBuffer, (unsigned char*)&kODoHNonce[0],
|
||||
static_cast<unsigned int>(strlen(kODoHNonce))};
|
||||
UniquePK11SymKey nonce;
|
||||
rv = HKDFExpand(odohPrk.get(), &nonceInfoItem, kAes128GcmNonceLen, false,
|
||||
nonce);
|
||||
if (rv != SECSuccess) {
|
||||
LOG(("ODoHDNSPacket::DecryptDNSResponse expand nonce failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
rv = PK11_ExtractKeyValue(nonce.get());
|
||||
if (rv != SECSuccess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SECItem* derivedItem = PK11_GetKeyData(nonce.get());
|
||||
if (!derivedItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// aad = 0x02 || 0x0000
|
||||
uint8_t aad[] = {0x2, 0, 0};
|
||||
|
||||
SECItem paramItem;
|
||||
CK_GCM_PARAMS param;
|
||||
param.pIv = derivedItem->data;
|
||||
param.ulIvLen = derivedItem->len;
|
||||
param.ulIvBits = param.ulIvLen * 8;
|
||||
param.ulTagBits = 16 * 8;
|
||||
param.pAAD = (CK_BYTE_PTR)aad;
|
||||
param.ulAADLen = 3;
|
||||
|
||||
paramItem.type = siBuffer;
|
||||
paramItem.data = (unsigned char*)(¶m);
|
||||
paramItem.len = sizeof(CK_GCM_PARAMS);
|
||||
|
||||
memset(mResponse, 0, mBodySize);
|
||||
rv = PK11_Decrypt(key.get(), CKM_AES_GCM, ¶mItem, mResponse, &mBodySize,
|
||||
MAX_SIZE, message.mEncryptedMessage.Elements(),
|
||||
message.mEncryptedMessage.Length());
|
||||
if (rv != SECSuccess) {
|
||||
LOG(("ODoHDNSPacket::DecryptDNSResponse decrypt failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "mozilla/Result.h"
|
||||
#include "nsHostResolver.h"
|
||||
#include "pk11pub.h"
|
||||
#include "ScopedNSSTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -95,6 +97,13 @@ class ODoHDNSPacket final : public DNSPacket {
|
|||
uint32_t& aTTL) override;
|
||||
|
||||
protected:
|
||||
bool EncryptDNSQuery(const nsACString& aQuery, uint16_t aPaddingLen,
|
||||
const ObliviousDoHConfig& aConfig,
|
||||
ObliviousDoHMessage& aOut);
|
||||
bool DecryptDNSResponse();
|
||||
|
||||
HpkeContext* mContext = nullptr;
|
||||
UniqueSECItem mPlainQuery;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
|
|
@ -299,6 +299,7 @@ PK11_DeleteTokenPublicKey
|
|||
PK11_DeleteTokenSymKey
|
||||
PK11_DEREncodePublicKey
|
||||
PK11_Derive
|
||||
PK11_DeriveWithFlags
|
||||
PK11_DeriveWithTemplate
|
||||
PK11_DestroyContext
|
||||
PK11_DestroyGenericObject
|
||||
|
@ -370,9 +371,21 @@ PK11_GetTokenURI
|
|||
PK11_HasAttributeSet
|
||||
PK11_HashBuf
|
||||
PK11_HasRootCerts
|
||||
PK11_HPKE_DestroyContext
|
||||
PK11_HPKE_Deserialize
|
||||
PK11_HPKE_ExportSecret
|
||||
PK11_HPKE_GetEncapPubKey
|
||||
PK11_HPKE_NewContext
|
||||
PK11_HPKE_Open
|
||||
PK11_HPKE_Seal
|
||||
PK11_HPKE_Serialize
|
||||
PK11_HPKE_SetupS
|
||||
PK11_HPKE_SetupR
|
||||
PK11_HPKE_ValidateParameters
|
||||
PK11_ImportCert
|
||||
PK11_ImportCertForKey
|
||||
PK11_ImportCRL
|
||||
PK11_ImportDataKey
|
||||
PK11_ImportDERPrivateKeyInfoAndReturnKey
|
||||
PK11_ImportEncryptedPrivateKeyInfoAndReturnKey
|
||||
PK11_ImportPublicKey
|
||||
|
|
Загрузка…
Ссылка в новой задаче