Skip to content

Commit

Permalink
Update SPAKE2p pairing code to match spec (#4166)
Browse files Browse the repository at this point in the history
* Update SPAKE2p pairing code to match spec

- update message handshake to include PBKDF param exchange
- update msg types and error codes
- add error handling via error message handshake

* delete commented out code

* use little endian byte ordering in the messages

* address review comments

* fix build
  • Loading branch information
pan-apple authored Dec 12, 2020
1 parent 8a75ed7 commit 34d8115
Show file tree
Hide file tree
Showing 10 changed files with 526 additions and 160 deletions.
20 changes: 12 additions & 8 deletions src/crypto/CHIPCryptoPAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ Spake2p::Spake2p(size_t _fe_size, size_t _point_size, size_t _hash_size)
tempbn = nullptr;
}

CHIP_ERROR Spake2p::Init(const uint8_t * context, size_t context_len)
CHIP_ERROR Spake2p::Init(const Hash_SHA256_stream * context)
{
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
state = CHIP_SPAKE2P_STATE::PREINIT;

error = InitImpl();
error = InitImpl(context);
VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);

error = PointLoad(spake2p_M_p256, sizeof(spake2p_M_p256), M);
Expand All @@ -96,9 +96,6 @@ CHIP_ERROR Spake2p::Init(const uint8_t * context, size_t context_len)
error = PointLoad(spake2p_N_p256, sizeof(spake2p_N_p256), N);
VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);

error = InternalHash(context, context_len);
VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);

state = CHIP_SPAKE2P_STATE::INIT;
error = CHIP_NO_ERROR;
exit:
Expand Down Expand Up @@ -387,12 +384,19 @@ CHIP_ERROR Spake2p::GetKeys(uint8_t * out, size_t * out_len)
return error;
}

CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitImpl()
CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitImpl(const Hash_SHA256_stream * context)
{
CHIP_ERROR error = CHIP_ERROR_INTERNAL;

error = sha256_hash_ctx.Begin();
VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
if (context != nullptr)
{
sha256_hash_ctx = (*context);
}
else
{
error = sha256_hash_ctx.Begin();
VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
}

error = InitInternal();
VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
Expand Down
15 changes: 8 additions & 7 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ CHIP_ERROR Hash_SHA256(const uint8_t * data, size_t data_length, uint8_t * out_b

/**
* @brief A class that defines stream based implementation of SHA-256 hash
* It's expected that the object of this class can be safely copied.
* All implementations must check for std::is_trivially_copyable.
**/

struct HashSHA256OpaqueContext
Expand Down Expand Up @@ -456,14 +458,13 @@ class Spake2p
/**
* @brief Initialize Spake2+ with some context specific information.
*
* @param context The context is arbitrary but should include information about the
* protocol being run, contain the transcript for negotiation, include
* the PKBDF parameters, etc.
* @param context_len The length of the context.
* @param context The spake2p session will bootstrap from this hash context.
* If the provided context pointer is null, the spake2p session will bootstrap
* from a blank hash context.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Init(const uint8_t * context, size_t context_len);
CHIP_ERROR Init(const Hash_SHA256_stream * context);

/**
* @brief Start the Spake2+ process as a verifier (i.e. an accessory being provisioned).
Expand Down Expand Up @@ -716,7 +717,7 @@ class Spake2p
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
virtual CHIP_ERROR InitImpl() = 0;
virtual CHIP_ERROR InitImpl(const Hash_SHA256_stream * context) = 0;

/**
* @brief Hash in_len bytes of in into the internal hash context.
Expand Down Expand Up @@ -828,7 +829,7 @@ class Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p
CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len) override;

protected:
CHIP_ERROR InitImpl() override;
CHIP_ERROR InitImpl(const Hash_SHA256_stream * context) override;
CHIP_ERROR Hash(const uint8_t * in, size_t in_len) override;
CHIP_ERROR HashFinalize(uint8_t * out) override;
CHIP_ERROR KDF(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length, const uint8_t * info,
Expand Down
5 changes: 4 additions & 1 deletion src/crypto/CHIPCryptoPALOpenSSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "CHIPCryptoPAL.h"

#include <type_traits>

#include <openssl/bn.h>
#include <openssl/conf.h>
#include <openssl/ec.h>
Expand Down Expand Up @@ -298,7 +300,8 @@ Hash_SHA256_stream::~Hash_SHA256_stream() {}

static inline SHA256_CTX * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context)
{
nlSTATIC_ASSERT_PRINT(sizeof(HashSHA256OpaqueContext) >= sizeof(SHA256_CTX), "Need more memory for SHA256 Context");
static_assert(sizeof(HashSHA256OpaqueContext) >= sizeof(SHA256_CTX), "Need more memory for SHA256 Context");
static_assert(std::is_trivially_copyable<SHA256_CTX>(), "SHA256_CTX values must copyable");
return reinterpret_cast<SHA256_CTX *>(context->mOpaque);
}

Expand Down
5 changes: 4 additions & 1 deletion src/crypto/CHIPCryptoPALmbedTLS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "CHIPCryptoPAL.h"

#include <type_traits>

#include <mbedtls/bignum.h>
#include <mbedtls/ccm.h>
#include <mbedtls/ctr_drbg.h>
Expand Down Expand Up @@ -192,7 +194,8 @@ Hash_SHA256_stream::~Hash_SHA256_stream(void) {}

static inline mbedtls_sha256_context * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context)
{
nlSTATIC_ASSERT_PRINT(sizeof(context->mOpaque) >= sizeof(mbedtls_sha256_context), "Need more memory for SHA256 Context");
static_assert(sizeof(context->mOpaque) >= sizeof(mbedtls_sha256_context), "Need more memory for SHA256 Context");
static_assert(std::is_trivially_copyable<mbedtls_sha256_context>(), "mbedtls_sha256_context values must copyable");
return reinterpret_cast<mbedtls_sha256_context *>(context->mOpaque);
}

Expand Down
26 changes: 17 additions & 9 deletions src/crypto/tests/CHIPCryptoPALTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ static void TestSPAKE2P_spake2p_FEMul(nlTestSuite * inSuite, void * inContext)
const struct spake2p_fe_mul_tv * vector = fe_mul_tvs[vectorIndex];

Spake2p_P256_SHA256_HKDF_HMAC spake2p;
CHIP_ERROR err = spake2p.Init(nullptr, 0);
CHIP_ERROR err = spake2p.Init(nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = spake2p.FELoad(vector->fe1, vector->fe1_len, spake2p.w0);
Expand Down Expand Up @@ -1022,7 +1022,7 @@ static void TestSPAKE2P_spake2p_FELoadWrite(nlTestSuite * inSuite, void * inCont
const struct spake2p_fe_rw_tv * vector = fe_rw_tvs[vectorIndex];

Spake2p_P256_SHA256_HKDF_HMAC spake2p;
CHIP_ERROR err = spake2p.Init(nullptr, 0);
CHIP_ERROR err = spake2p.Init(nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = spake2p.FELoad(vector->fe_in, vector->fe_in_len, spake2p.w0);
Expand All @@ -1049,7 +1049,7 @@ static void TestSPAKE2P_spake2p_Mac(nlTestSuite * inSuite, void * inContext)
const struct spake2p_hmac_tv * vector = hmac_tvs[vectorIndex];

Spake2p_P256_SHA256_HKDF_HMAC spake2p;
CHIP_ERROR err = spake2p.Init(nullptr, 0);
CHIP_ERROR err = spake2p.Init(nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = spake2p.Mac(vector->key, vector->key_len, vector->input, vector->input_len, mac);
Expand Down Expand Up @@ -1079,7 +1079,7 @@ static void TestSPAKE2P_spake2p_PointMul(nlTestSuite * inSuite, void * inContext
const struct spake2p_point_mul_tv * vector = point_mul_tvs[vectorIndex];

Spake2p_P256_SHA256_HKDF_HMAC spake2p;
CHIP_ERROR err = spake2p.Init(nullptr, 0);
CHIP_ERROR err = spake2p.Init(nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = spake2p.PointLoad(vector->point, vector->point_len, spake2p.L);
Expand Down Expand Up @@ -1115,7 +1115,7 @@ static void TestSPAKE2P_spake2p_PointMulAdd(nlTestSuite * inSuite, void * inCont
const struct spake2p_point_muladd_tv * vector = point_muladd_tvs[vectorIndex];

Spake2p_P256_SHA256_HKDF_HMAC spake2p;
CHIP_ERROR err = spake2p.Init(nullptr, 0);
CHIP_ERROR err = spake2p.Init(nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = spake2p.PointLoad(vector->point1, vector->point1_len, spake2p.X);
Expand Down Expand Up @@ -1157,7 +1157,7 @@ static void TestSPAKE2P_spake2p_PointLoadWrite(nlTestSuite * inSuite, void * inC
const struct spake2p_point_rw_tv * vector = point_rw_tvs[vectorIndex];

Spake2p_P256_SHA256_HKDF_HMAC spake2p;
CHIP_ERROR err = spake2p.Init(nullptr, 0);
CHIP_ERROR err = spake2p.Init(nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = spake2p.PointLoad(vector->point, vector->point_len, spake2p.L);
Expand All @@ -1183,7 +1183,7 @@ static void TestSPAKE2P_spake2p_PointIsValid(nlTestSuite * inSuite, void * inCon
const struct spake2p_point_valid_tv * vector = point_valid_tvs[vectorIndex];

Spake2p_P256_SHA256_HKDF_HMAC spake2p;
CHIP_ERROR err = spake2p.Init(nullptr, 0);
CHIP_ERROR err = spake2p.Init(nullptr);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

err = spake2p.PointLoad(vector->point, vector->point_len, spake2p.L);
Expand Down Expand Up @@ -1255,8 +1255,16 @@ static void TestSPAKE2P_RFC(nlTestSuite * inSuite, void * inContext)
Test_Spake2p_P256_SHA256_HKDF_HMAC Verifier;
Test_Spake2p_P256_SHA256_HKDF_HMAC Prover;

Hash_SHA256_stream hashContext;

error = hashContext.Begin();
NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR);

error = hashContext.AddData(vector->context, vector->context_len);
NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR);

// First start the prover
error = Prover.Init(vector->context, vector->context_len);
error = Prover.Init(&hashContext);
NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR);

error = Prover.BeginProver(vector->prover_identity, vector->prover_identity_len, vector->verifier_identity,
Expand All @@ -1275,7 +1283,7 @@ static void TestSPAKE2P_RFC(nlTestSuite * inSuite, void * inContext)
NL_TEST_ASSERT(inSuite, memcmp(X, vector->X, vector->X_len) == 0);

// Start up the verifier
error = Verifier.Init(vector->context, vector->context_len);
error = Verifier.Init(&hashContext);
NL_TEST_ASSERT(inSuite, error == CHIP_NO_ERROR);

// First pre-compute L (accessories with dynamic setup codes will do this)
Expand Down
Loading

0 comments on commit 34d8115

Please sign in to comment.