Skip to content

Commit

Permalink
Move Spake2p Verifier class to CHIPCryptoPAL (#15329)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexhqwang authored Feb 18, 2022
1 parent 4ccdb16 commit 9279ab2
Show file tree
Hide file tree
Showing 19 changed files with 203 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ class OpenCommissioningWindowCommand : public CHIPCommand
AddArgument("node-id", 0, UINT64_MAX, &mNodeId);
AddArgument("option", 0, 2, &mCommissioningWindowOption);
AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
AddArgument("iteration", chip::Crypto::kSpake2pPBKDFMinimumIterations, chip::Crypto::kSpake2pPBKDFMaximumIterations,
&mIteration);
AddArgument("iteration", chip::kSpake2p_Min_PBKDF_Iterations, chip::kSpake2p_Max_PBKDF_Iterations, &mIteration);
AddArgument("discriminator", 0, 4096, &mDiscriminator);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(
auto & passcodeID = commandData.passcodeID;

Optional<StatusCode> status = Optional<StatusCode>::Missing();
PASEVerifier verifier;
Spake2pVerifier verifier;

ChipLogProgress(Zcl, "Received command to open commissioning window");

Expand All @@ -109,13 +109,13 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(
VerifyOrExit(Server::GetInstance().GetCommissioningWindowManager().CommissioningWindowStatus() ==
CommissioningWindowStatus::kWindowNotOpen,
status.Emplace(StatusCode::EMBER_ZCL_STATUS_CODE_BUSY));
VerifyOrExit(iterations >= Crypto::kSpake2pPBKDFMinimumIterations,
VerifyOrExit(iterations >= kSpake2p_Min_PBKDF_Iterations,
status.Emplace(StatusCode::EMBER_ZCL_STATUS_CODE_PAKE_PARAMETER_ERROR));
VerifyOrExit(iterations <= Crypto::kSpake2pPBKDFMaximumIterations,
VerifyOrExit(iterations <= kSpake2p_Max_PBKDF_Iterations,
status.Emplace(StatusCode::EMBER_ZCL_STATUS_CODE_PAKE_PARAMETER_ERROR));
VerifyOrExit(salt.size() >= Crypto::kSpake2pPBKDFMinimumSaltLen,
VerifyOrExit(salt.size() >= kSpake2p_Min_PBKDF_Salt_Length,
status.Emplace(StatusCode::EMBER_ZCL_STATUS_CODE_PAKE_PARAMETER_ERROR));
VerifyOrExit(salt.size() <= Crypto::kSpake2pPBKDFMaximumSaltLen,
VerifyOrExit(salt.size() <= kSpake2p_Max_PBKDF_Salt_Length,
status.Emplace(StatusCode::EMBER_ZCL_STATUS_CODE_PAKE_PARAMETER_ERROR));
VerifyOrExit(commissioningTimeout <= kMaxCommissionioningTimeoutSeconds,
status.Emplace(StatusCode::EMBER_ZCL_STATUS_CODE_PAKE_PARAMETER_ERROR));
Expand Down
22 changes: 11 additions & 11 deletions src/app/server/CommissioningWindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,18 @@ CHIP_ERROR CommissioningWindowManager::OpenCommissioningWindow()
}
else
{
uint32_t iterationCount = 0;
uint8_t salt[Crypto::kSpake2pPBKDFMaximumSaltLen] = { 0 };
size_t saltLen = 0;
PASEVerifierSerialized serializedVerifier = { 0 };
size_t serializedVerifierLen = 0;
PASEVerifier verifier;
uint32_t iterationCount = 0;
uint8_t salt[kSpake2p_Max_PBKDF_Salt_Length] = { 0 };
size_t saltLen = 0;
Spake2pVerifierSerialized serializedVerifier = { 0 };
size_t serializedVerifierLen = 0;
Spake2pVerifier verifier;

ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSpake2pIterationCount(iterationCount));
ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSpake2pSalt(salt, sizeof(salt), saltLen));
ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSpake2pVerifier(
serializedVerifier, Crypto::kSpake2pSerializedVerifierSize, serializedVerifierLen));
VerifyOrReturnError(Crypto::kSpake2pSerializedVerifierSize == serializedVerifierLen, CHIP_ERROR_INVALID_ARGUMENT);
serializedVerifier, kSpake2p_VerifierSerialized_Length, serializedVerifierLen));
VerifyOrReturnError(kSpake2p_VerifierSerialized_Length == serializedVerifierLen, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(verifier.Deserialize(ByteSpan(serializedVerifier)));

ReturnErrorOnFailure(
Expand Down Expand Up @@ -239,8 +239,8 @@ CHIP_ERROR CommissioningWindowManager::OpenBasicCommissioningWindow(uint16_t com
}

CHIP_ERROR CommissioningWindowManager::OpenEnhancedCommissioningWindow(uint16_t commissioningTimeoutSeconds, uint16_t discriminator,
PASEVerifier & verifier, uint32_t iterations, ByteSpan salt,
PasscodeId passcodeID)
Spake2pVerifier & verifier, uint32_t iterations,
ByteSpan salt, PasscodeId passcodeID)
{
// Once a device is operational, it shall be commissioned into subsequent fabrics using
// the operational network only.
Expand All @@ -258,7 +258,7 @@ CHIP_ERROR CommissioningWindowManager::OpenEnhancedCommissioningWindow(uint16_t
mECMPasscodeID = passcodeID;
mECMIterations = iterations;

memcpy(&mECMPASEVerifier, &verifier, sizeof(PASEVerifier));
memcpy(&mECMPASEVerifier, &verifier, sizeof(Spake2pVerifier));

mUseECM = true;

Expand Down
6 changes: 3 additions & 3 deletions src/app/server/CommissioningWindowManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class CommissioningWindowManager : public SessionEstablishmentDelegate
CommissioningWindowAdvertisement advertisementMode = chip::CommissioningWindowAdvertisement::kAllSupported);

CHIP_ERROR OpenEnhancedCommissioningWindow(uint16_t commissioningTimeoutSeconds, uint16_t discriminator,
PASEVerifier & verifier, uint32_t iterations, chip::ByteSpan salt,
Spake2pVerifier & verifier, uint32_t iterations, chip::ByteSpan salt,
PasscodeId passcodeID);

void CloseCommissioningWindow();
Expand Down Expand Up @@ -106,12 +106,12 @@ class CommissioningWindowManager : public SessionEstablishmentDelegate
uint8_t mFailedCommissioningAttempts = 0;

bool mUseECM = false;
PASEVerifier mECMPASEVerifier;
Spake2pVerifier mECMPASEVerifier;
uint16_t mECMDiscriminator = 0;
PasscodeId mECMPasscodeID = kDefaultCommissioningPasscodeId;
uint32_t mECMIterations = 0;
uint32_t mECMSaltLength = 0;
uint8_t mECMSalt[Crypto::kSpake2pPBKDFMaximumSaltLen];
uint8_t mECMSalt[kSpake2p_Max_PBKDF_Salt_Length];
};

} // namespace chip
6 changes: 3 additions & 3 deletions src/app/tests/TestCommissionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ void CheckCommissioningWindowManagerEnhancedWindowTask(intptr_t context)
CHIP_ERROR err = chip::DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(originDiscriminator);
NL_TEST_ASSERT(suite, err == CHIP_NO_ERROR);
uint16_t newDiscriminator = static_cast<uint16_t>(originDiscriminator + 1);
chip::PASEVerifier verifier;
constexpr uint32_t kIterations = chip::Crypto::kSpake2pPBKDFMinimumIterations;
uint8_t salt[chip::Crypto::kSpake2pPBKDFMinimumSaltLen];
chip::Spake2pVerifier verifier;
constexpr uint32_t kIterations = chip::kSpake2p_Min_PBKDF_Iterations;
uint8_t salt[chip::kSpake2p_Min_PBKDF_Salt_Length];
chip::ByteSpan saltData(salt);
constexpr chip::PasscodeId kPasscodeID = 1;
uint16_t currentDiscriminator;
Expand Down
6 changes: 3 additions & 3 deletions src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ void DeviceController::OnOpenPairingWindowFailureResponse(void * context, CHIP_E
}

CHIP_ERROR DeviceController::ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt,
PASEVerifier & outVerifier, PasscodeId & outPasscodeId)
Spake2pVerifier & outVerifier, PasscodeId & outPasscodeId)
{
ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(outVerifier, iterations, salt, /* useRandomPIN= */ false, setupPincode));

Expand Down Expand Up @@ -506,12 +506,12 @@ CHIP_ERROR DeviceController::OpenCommissioningWindowInternal()
const char kSpake2pKeyExchangeSalt[] = "SPAKE2P Key Salt";
ByteSpan salt(Uint8::from_const_char(kSpake2pKeyExchangeSalt), sizeof(kSpake2pKeyExchangeSalt));
bool randomSetupPIN = (mCommissioningWindowOption == CommissioningWindowOption::kTokenWithRandomPIN);
PASEVerifier verifier;
Spake2pVerifier verifier;

ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(verifier, mCommissioningWindowIteration, salt, randomSetupPIN,
mSetupPayload.setUpPINCode));

chip::PASEVerifierSerialized serializedVerifier;
chip::Spake2pVerifierSerialized serializedVerifier;
MutableByteSpan serializedVerifierSpan(serializedVerifier);
ReturnErrorOnFailure(verifier.Serialize(serializedVerifierSpan));

Expand Down
4 changes: 2 additions & 2 deletions src/controller/CHIPDeviceController.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,12 @@ class DLL_EXPORT DeviceController : public SessionRecoveryDelegate
* @param[in] iterations The number of iterations to use when generating the verifier
* @param[in] setupPincode The desired PIN code to use
* @param[in] salt The 16-byte salt for verifier computation
* @param[out] outVerifier The PASEVerifier to be populated on success
* @param[out] outVerifier The Spake2pVerifier to be populated on success
* @param[out] outPasscodeId The passcode ID to be populated on success
*
* @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error
*/
CHIP_ERROR ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt, PASEVerifier & outVerifier,
CHIP_ERROR ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt, Spake2pVerifier & outVerifier,
PasscodeId & outPasscodeId);

/**
Expand Down
7 changes: 3 additions & 4 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,8 @@ JNI_METHOD(jobject, computePaseVerifier)
jobject params;
jbyteArray verifierBytes;
PasscodeId passcodeId;
PASEVerifier verifier;
PASEVerifierSerialized serializedVerifier;
Spake2pVerifier verifier;
Spake2pVerifierSerialized serializedVerifier;
MutableByteSpan serializedVerifierSpan(serializedVerifier);
JniByteArray jniSalt(env, salt);

Expand All @@ -644,8 +644,7 @@ JNI_METHOD(jobject, computePaseVerifier)
err = verifier.Serialize(serializedVerifierSpan);
SuccessOrExit(err);

err =
JniReferences::GetInstance().N2J_ByteArray(env, serializedVerifier, Crypto::kSpake2pSerializedVerifierSize, verifierBytes);
err = JniReferences::GetInstance().N2J_ByteArray(env, serializedVerifier, kSpake2p_VerifierSerialized_Length, verifierBytes);
SuccessOrExit(err);

err = N2J_PaseVerifierParams(env, setupPincode, static_cast<jlong>(passcodeId), verifierBytes, params);
Expand Down
74 changes: 74 additions & 0 deletions src/crypto/CHIPCryptoPAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,80 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeW0(uint8_t * w0out, size_t * w0
return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Serialize(MutableByteSpan & outSerialized)
{
VerifyOrReturnError(outSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

memcpy(&outSerialized.data()[0], mW0, sizeof(mW0));
memcpy(&outSerialized.data()[sizeof(mW0)], mL, sizeof(mL));

outSerialized.reduce_size(kSpake2p_VerifierSerialized_Length);

return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Deserialize(ByteSpan inSerialized)
{
VerifyOrReturnError(inSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

memcpy(mW0, &inSerialized.data()[0], sizeof(mW0));
memcpy(mL, &inSerialized.data()[sizeof(mW0)], sizeof(mL));

return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t & setupPin)
{
uint8_t serializedWS[kSpake2p_WS_Length * 2] = { 0 };
ReturnErrorOnFailure(ComputeWS(pbkdf2IterCount, salt, setupPin, serializedWS, sizeof(serializedWS)));

CHIP_ERROR err = CHIP_NO_ERROR;
size_t len;

// Create local Spake2+ object for w0 and L computations.
#ifdef ENABLE_HSM_SPAKE
Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p;
#else
Spake2p_P256_SHA256_HKDF_HMAC spake2p;
#endif
uint8_t context[kSHA256_Hash_Length] = { 0 };
SuccessOrExit(err = spake2p.Init(context, sizeof(context)));

// Compute w0
len = sizeof(mW0);
SuccessOrExit(err = spake2p.ComputeW0(mW0, &len, &serializedWS[0], kSpake2p_WS_Length));
VerifyOrExit(len == sizeof(mW0), err = CHIP_ERROR_INTERNAL);

// Compute L
len = sizeof(mL);
SuccessOrExit(err = spake2p.ComputeL(mL, &len, &serializedWS[kSpake2p_WS_Length], kSpake2p_WS_Length));
VerifyOrExit(len == sizeof(mL), err = CHIP_ERROR_INTERNAL);

exit:
spake2p.Clear();
return err;
}

CHIP_ERROR Spake2pVerifier::ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t & setupPin, uint8_t * ws,
uint32_t ws_len)
{
#ifdef ENABLE_HSM_PBKDF2
PBKDF2_sha256HSM pbkdf2;
#else
PBKDF2_sha256 pbkdf2;
#endif
uint8_t littleEndianSetupPINCode[sizeof(uint32_t)];
Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setupPin);

ReturnErrorCodeIf(salt.size() < kSpake2p_Min_PBKDF_Salt_Length || salt.size() > kSpake2p_Max_PBKDF_Salt_Length,
CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorCodeIf(pbkdf2IterCount < kSpake2p_Min_PBKDF_Iterations || pbkdf2IterCount > kSpake2p_Max_PBKDF_Iterations,
CHIP_ERROR_INVALID_ARGUMENT);

return pbkdf2.pbkdf2_sha256(littleEndianSetupPINCode, sizeof(littleEndianSetupPINCode), salt.data(), salt.size(),
pbkdf2IterCount, ws_len, ws);
}

CHIP_ERROR ConvertIntegerRawToDerWithoutTag(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer)
{
return ConvertIntegerRawToDerInternal(raw_integer, out_der_integer, /* include_tag_and_length = */ false);
Expand Down
78 changes: 56 additions & 22 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ constexpr size_t kMAX_CSR_Length = 255;

constexpr size_t CHIP_CRYPTO_HASH_LEN_BYTES = kSHA256_Hash_Length;

constexpr size_t kMin_Salt_Length = 16;
constexpr size_t kMax_Salt_Length = 32;
constexpr size_t kSpake2p_Min_PBKDF_Salt_Length = 16;
constexpr size_t kSpake2p_Max_PBKDF_Salt_Length = 32;
constexpr uint32_t kSpake2p_Min_PBKDF_Iterations = 1000;
constexpr uint32_t kSpake2p_Max_PBKDF_Iterations = 100000;

constexpr size_t kP256_PrivateKey_Length = CHIP_CRYPTO_GROUP_SIZE_BYTES;
constexpr size_t kP256_PublicKey_Length = CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES;
Expand All @@ -92,6 +94,9 @@ constexpr size_t kEmitDerIntegerOverhead = 3; // Tag + Length byte + 1

constexpr size_t kMAX_Hash_SHA256_Context_Size = CHIP_CONFIG_SHA256_CONTEXT_SIZE;

constexpr size_t kSpake2p_WS_Length = kP256_FE_Length + 8;
constexpr size_t kSpake2p_VerifierSerialized_Length = kP256_FE_Length + kP256_Point_Length;

/*
* Overhead to encode a raw ECDSA signature in X9.62 format in ASN.1 DER
*
Expand Down Expand Up @@ -134,26 +139,6 @@ const uint8_t spake2p_N_p256[65] = {
0xd3, 0x60, 0x34, 0x80, 0x8c, 0xd5, 0x64, 0x49, 0x0b, 0x1e, 0x65, 0x6e, 0xdb, 0xe7,
};

/** @brief Spake2p parameters.
*
* Specifications section 3.9. Password-Based Key Derivation Function
* Specifications section 5.1.1.6
**/
constexpr uint32_t kSpake2pPBKDFMinimumIterations = 1000;
constexpr uint32_t kSpake2pPBKDFMaximumIterations = 100000;
constexpr uint32_t kSpake2pPBKDFMinimumSaltLen = 16;
constexpr uint32_t kSpake2pPBKDFMaximumSaltLen = 32;

/** @brief Serialized format of the PASE Verifier components.
*
* This is used when the Verifier should be presented in a serialized form.
* For example, when it is generated using PBKDF function, when stored in the
* memory or when sent over the wire.
* The serialized format is concatentation of { W0, L } verifier components
* as per Specifications section 3.10. Password-Authenticated Key Exchange.
**/
constexpr size_t kSpake2pSerializedVerifierSize = kP256_FE_Length + kP256_Point_Length;

/**
* Spake2+ state machine to ensure proper execution of the protocol.
*/
Expand Down Expand Up @@ -1258,6 +1243,55 @@ class Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p
Spake2pOpaqueContext mSpake2pContext;
};

/**
* @brief Class used for verifying PASE secure sessions.
**/
class Spake2pVerifier
{
public:
uint8_t mW0[kP256_FE_Length];
uint8_t mL[kP256_Point_Length];

CHIP_ERROR Serialize(MutableByteSpan & outSerialized);
CHIP_ERROR Deserialize(ByteSpan inSerialized);

/**
* @brief Generate the Spake2+ verifier.
*
* @param pbkdf2IterCount Iteration count for PBKDF2 function
* @param salt Salt to be used for Spake2+ operation
* @param setupPin Provided setup PIN (passcode)
*
* @return CHIP_ERROR The result of Spake2+ verifier generation
*/
CHIP_ERROR Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t & setupPin);

/**
* @brief Compute the initiator values (w0, w1) used for PAKE input.
*
* @param pbkdf2IterCount Iteration count for PBKDF2 function
* @param salt Salt to be used for Spake2+ operation
* @param setupPin Provided setup PIN (passcode)
* @param ws The output pair (w0, w1) stored sequentially
* @param ws_len The output length
*
* @return CHIP_ERROR The result from running PBKDF2
*/
static CHIP_ERROR ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t & setupPin, uint8_t * ws,
uint32_t ws_len);
};

/**
* @brief Serialized format of the Spake2+ Verifier components.
*
* This is used when the Verifier should be presented in a serialized form.
* For example, when it is generated using PBKDF function, when stored in the
* memory or when sent over the wire.
* The serialized format is concatentation of 'W0' and 'L' verifier components:
* { Spake2pVerifier.mW0[kP256_FE_Length], Spake2pVerifier.mL[kP256_Point_Length] }
**/
typedef uint8_t Spake2pVerifierSerialized[kSpake2p_VerifierSerialized_Length];

/**
* @brief Compute the compressed fabric identifier used for operational discovery service
* records from a Node's root public key and Fabric ID. On success, out_compressed_fabric_id
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/CHIPCryptoPALOpenSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,8 @@ CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, c
VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen >= kMin_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen <= kMax_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);

Expand Down
4 changes: 2 additions & 2 deletions src/crypto/CHIPCryptoPALmbedTLS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,8 @@ CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, c
VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen >= kMin_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen <= kMax_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);

Expand Down
Loading

0 comments on commit 9279ab2

Please sign in to comment.