Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spake2p: generate verifier sets with specified PIN codes in a file #23606

Merged
merged 4 commits into from
Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 61 additions & 7 deletions src/tools/spake2p/Cmd_GenVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "spake2p.h"

#include <errno.h>
#include <stdio.h>

#include <CHIPVersion.h>
#include <crypto/CHIPCryptoPAL.h>
Expand All @@ -52,6 +53,7 @@ OptionDef gCmdOptionDefs[] =
{
{ "count", kArgumentRequired, 'c' },
{ "pin-code", kArgumentRequired, 'p' },
{ "pin-code-file", kArgumentRequired, 'f' },
{ "iteration-count", kArgumentRequired, 'i' },
{ "salt-len", kArgumentRequired, 'l' },
{ "salt", kArgumentRequired, 's' },
Expand Down Expand Up @@ -85,6 +87,20 @@ const char * const gCmdOptionHelp =
" * 12345678\n"
" * 87654321\n"
"\n"
" -f, --pin-code-file <file>\n"
"\n"
" A file which contains all the PIN codes to generate verifiers.\n"
" Each line in this file should be a valid PIN code in the decimal number format. If the row count\n"
" of this file is less than the number of pin-code/verifier parameter sets to be generated, the\n"
" first few verifier sets will be generated using the PIN codes in this file, and the next will\n"
" use the random PIN codes.\n"
" The following file is a example with 5 PIN codes:\n"
" 1234\n"
" 2345\n"
" 3456\n"
" 4567\n"
" 5678\n"
"\n"
" -i, --iteration-count <int>\n"
"\n"
" SPAKE2P PBKDF iteration count. The value should be positive integer in range [1000..100000].\n"
Expand Down Expand Up @@ -143,6 +159,33 @@ uint8_t gSalt[BASE64_MAX_DECODED_LEN(BASE64_ENCODED_LEN(chip::kSpake2p_Max_PBKDF
uint8_t gSaltDecodedLen = 0;
uint8_t gSaltLen = 0;
const char * gOutFileName = nullptr;
FILE * gPinCodeFile = nullptr;

static uint32_t GetNextPinCode()
{
if (!gPinCodeFile)
{
return chip::kSetupPINCodeUndefinedValue;
}
char * pinCodeStr = nullptr;
size_t readSize = 8;
uint32_t pinCode = chip::kSetupPINCodeUndefinedValue;
if (getline(&pinCodeStr, &readSize, gPinCodeFile) != -1)
{
if (readSize > 8)
{
pinCodeStr[8] = 0;
}
pinCode = static_cast<uint32_t>(atoi(pinCodeStr));
if (!chip::SetupPayload::IsValidSetupPIN(pinCode))
{
fprintf(stderr, "The line %s in PIN codes file is invalid, using a random PIN code.\n", pinCodeStr);
pinCode = chip::kSetupPINCodeUndefinedValue;
}
free(pinCodeStr);
}
return pinCode;
}

bool HandleOption(const char * progName, OptionSet * optSet, int id, const char * name, const char * arg)
{
Expand All @@ -157,17 +200,23 @@ bool HandleOption(const char * progName, OptionSet * optSet, int id, const char
break;
case 'p':
// Specifications sections 5.1.1.6 and 5.1.6.1
if (!ParseInt(arg, gPinCode) || (gPinCode > chip::kSetupPINCodeMaximumValue) ||
(gPinCode == chip::kSetupPINCodeUndefinedValue) || (gPinCode == 11111111) || (gPinCode == 22222222) ||
(gPinCode == 33333333) || (gPinCode == 44444444) || (gPinCode == 55555555) || (gPinCode == 66666666) ||
(gPinCode == 77777777) || (gPinCode == 88888888) || (gPinCode == 99999999) || (gPinCode == 12345678) ||
(gPinCode == 87654321))
if (!ParseInt(arg, gPinCode) || (!chip::SetupPayload::IsValidSetupPIN(gPinCode)))
{
PrintArgError("%s: Invalid value specified for pin-code parameter: %s\n", progName, arg);
return false;
}
break;

case 'f':
gPinCodeFile = fopen(arg, "r");
if (!gPinCodeFile)
{
PrintArgError("%s: Failed to open the PIN code file: %s\n", progName, arg);
return false;
}
gPinCode = GetNextPinCode();
break;

case 'i':
if (!ParseInt(arg, gIterationCount) ||
!(gIterationCount >= chip::kSpake2p_Min_PBKDF_Iterations && gIterationCount <= chip::kSpake2p_Max_PBKDF_Iterations))
Expand Down Expand Up @@ -334,10 +383,15 @@ bool Cmd_GenVerifier(int argc, char * argv[])
return false;
}

// On the next iteration the PIN Code and Salt will be randomly generated.
gPinCode = chip::kSetupPINCodeUndefinedValue;
// If the file with PIN codes is not provided, the PIN code on next iteration will be randomly generated.
gPinCode = GetNextPinCode();
wqx6 marked this conversation as resolved.
Show resolved Hide resolved
// On the next iteration the Salt will be randomly generated.
gSaltDecodedLen = 0;
}

if (gPinCodeFile)
{
fclose(gPinCodeFile);
}
return true;
}
10 changes: 10 additions & 0 deletions src/tools/spake2p/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ random Salts and corresponding Verifiers):
```
./spake2p gen-verifier --count 100 --iteration-count 15000 --salt-len 32 --out spake2p-provisioning-data.csv
```

Example command that generates 100 sets of spake2p parameters (Specific PIN
Codes, random Salts and corresponding Verifiers):

wqx6 marked this conversation as resolved.
Show resolved Hide resolved
```
./spake2p gen-verifier --count 100 --pin-code-file pincodes.csv --iteration-count 15000 --salt-len 32 --out spake2p-provisioning-data.csv
```

Notes: Each line of the `pincodes.csv` should be a valid PIN code. You can use
`spake2p --help` to get the example content of the file.