Skip to content

Commit

Permalink
Update spake2p tool to take base64 salt
Browse files Browse the repository at this point in the history
  • Loading branch information
Damian-Nordic committed Jul 19, 2022
1 parent f5e83c3 commit 3832c09
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def gen_test_certs(chip_cert_exe: str,
new_certificates["PAI_CERT"] + ".der")


def gen_spake2p_params(spake2p_path: str, passcode: int, it: int, salt: str) -> dict:
def gen_spake2p_params(spake2p_path: str, passcode: int, it: int, salt: bytes) -> dict:
""" Generate Spake2+ params using external spake2p tool
Args:
Expand All @@ -186,7 +186,7 @@ def gen_spake2p_params(spake2p_path: str, passcode: int, it: int, salt: str) ->
cmd = [
spake2p_path, 'gen-verifier',
'--iteration-count', str(it),
'--salt', salt,
'--salt', base64.b64encode(salt),
'--pin-code', str(passcode),
'--out', '-',
]
Expand Down Expand Up @@ -344,7 +344,7 @@ def _add_entry(self, name: str, value: any):
def _generate_spake2_verifier(self):
""" If verifier has not been provided in arguments list it should be generated via external script """
spake2_params = gen_spake2p_params(self._args.spake2p_path, self._args.passcode,
self._args.spake2_it, self._args.spake2_salt.decode('ascii'))
self._args.spake2_it, self._args.spake2_salt)
return base64.b64decode(spake2_params["Verifier"])

def _generate_rotating_device_uid(self):
Expand Down
2 changes: 1 addition & 1 deletion src/include/platform/CHIPDeviceConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@
#error "Non-default Spake2+ salt configured but verifier left unchanged"
#endif

// Generated with: spake2p gen-verifier -o - -i 1000 -s "SPAKE2P Key Salt" -p 20202021
// Generated with: spake2p gen-verifier -o - -i 1000 -s "U1BBS0UyUCBLZXkgU2FsdA==" -p 20202021
#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER \
"uWFwqugDNGiEck/po7KHwwMwwqZgN10XuyBajPGuyzUEV/iree4lOrao5GuwnlQ65CJzbeUB49s31EH+NEkg0JVI5MGCQGMMT/SRPFNRODm3wH/MBiehuFc6FJ/" \
"NH6Rmzw=="
Expand Down
43 changes: 30 additions & 13 deletions src/tools/spake2p/Cmd_GenVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,12 @@ OptionSet *gCmdOptionSets[] =
};
// clang-format on

uint32_t gCount = 1;
uint32_t gPinCode = chip::kSetupPINCodeUndefinedValue;
uint32_t gIterationCount = 0;
uint32_t gCount = 1;
uint32_t gPinCode = chip::kSetupPINCodeUndefinedValue;
uint32_t gIterationCount = 0;
uint8_t gSalt[BASE64_MAX_DECODED_LEN(BASE64_ENCODED_LEN(chip::kSpake2p_Max_PBKDF_Salt_Length))];
uint8_t gSaltDecodedLen = 0;
uint8_t gSaltLen = 0;
const char * gSalt = nullptr;
const char * gOutFileName = nullptr;

bool HandleOption(const char * progName, OptionSet * optSet, int id, const char * name, const char * arg)
Expand Down Expand Up @@ -186,12 +187,28 @@ bool HandleOption(const char * progName, OptionSet * optSet, int id, const char
break;

case 's':
gSalt = arg;
if (!(strlen(gSalt) >= chip::kSpake2p_Min_PBKDF_Salt_Length && strlen(gSalt) <= chip::kSpake2p_Max_PBKDF_Salt_Length))
if (strlen(arg) > BASE64_ENCODED_LEN(chip::kSpake2p_Max_PBKDF_Salt_Length))
{
fprintf(stderr, "%s: Invalid legth of the specified salt parameter: %s\n", progName, arg);
fprintf(stderr, "%s: Salt parameter too long: %s\n", progName, arg);
return false;
}

gSaltDecodedLen = static_cast<uint8_t>(chip::Base64Decode32(arg, static_cast<uint32_t>(strlen(arg)), gSalt));

// The first check was just to make sure Base64Decode32 would not write beyond the buffer.
// Now double-check is the length is correct.
if (gSaltDecodedLen > chip::kSpake2p_Max_PBKDF_Salt_Length)
{
fprintf(stderr, "%s: Salt parameter too long: %s\n", progName, arg);
return false;
}

if (gSaltDecodedLen < chip::kSpake2p_Min_PBKDF_Salt_Length)
{
fprintf(stderr, "%s: Salt parameter too short: %s\n", progName, arg);
return false;
}

break;

case 'o':
Expand Down Expand Up @@ -227,19 +244,19 @@ bool Cmd_GenVerifier(int argc, char * argv[])
return false;
}

if (gSalt == nullptr && gSaltLen == 0)
if (gSaltDecodedLen == 0 && gSaltLen == 0)
{
fprintf(stderr, "Please specify at least one of the 'salt' or 'salt-len' parameters.\n");
return false;
}
if (gSalt != nullptr && gSaltLen != 0 && gSaltLen != strlen(gSalt))
if (gSaltDecodedLen != 0 && gSaltLen != 0 && gSaltDecodedLen != gSaltLen)
{
fprintf(stderr, "The specified 'salt-len' doesn't match the length of 'salt' parameter.\n");
return false;
}
if (gSaltLen == 0)
{
gSaltLen = static_cast<uint8_t>(strlen(gSalt));
gSaltLen = gSaltDecodedLen;
}

if (gOutFileName == nullptr)
Expand Down Expand Up @@ -271,7 +288,7 @@ bool Cmd_GenVerifier(int argc, char * argv[])
for (uint32_t i = 0; i < gCount; i++)
{
uint8_t salt[chip::kSpake2p_Max_PBKDF_Salt_Length];
if (gSalt == nullptr)
if (gSaltDecodedLen == 0)
{
CHIP_ERROR err = chip::Crypto::DRBG_get_bytes(salt, gSaltLen);
if (err != CHIP_NO_ERROR)
Expand Down Expand Up @@ -318,8 +335,8 @@ bool Cmd_GenVerifier(int argc, char * argv[])
}

// On the next iteration the PIN Code and Salt will be randomly generated.
gPinCode = chip::kSetupPINCodeUndefinedValue;
gSalt = nullptr;
gPinCode = chip::kSetupPINCodeUndefinedValue;
gSaltDecodedLen = 0;
}

return true;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/spake2p/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Specify '--help' option for detail instructions on command usage:
Example command that generates spake2p verifier for a given PIN code:

```
./spake2p gen-verifier --pin-code 45502684 --iteration-count 1000 --salt "SPAKE2P Key Salt 1" --out spake2p-provisioning-data.csv
./spake2p gen-verifier --pin-code 45502684 --iteration-count 1000 --salt "U1BBS0UyUCBLZXkgU2FsdA==" --out spake2p-provisioning-data.csv
```

Example command that generates 100 sets of spake2p parameters (random PIN Codes,
Expand Down

0 comments on commit 3832c09

Please sign in to comment.