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

[Telink] fix factory data as pr #23385 #23559

Merged
merged 2 commits into from
Nov 10, 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
6 changes: 4 additions & 2 deletions config/telink/chip-module/generate_factory_data.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ if(CONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS)
# convert decimal PID to its hexadecimal representation to find out certification files in repository
math(EXPR LOCAL_PID "${CONFIG_CHIP_DEVICE_PRODUCT_ID}" OUTPUT_FORMAT HEXADECIMAL)
string(SUBSTRING ${LOCAL_PID} 2 -1 raw_pid)
string(TOUPPER ${raw_pid} raw_pid_upper)
# all certs are located in ${CHIP_ROOT}/credentials/development/attestation
# it can be used during development without need to generate new certifications
string(APPEND script_args "--dac_cert \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid}-Cert.der\"\n")
string(APPEND script_args "--dac_key \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid}-Key.der\"\n")
string(APPEND script_args "--dac_cert \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid_upper}-Cert.der\"\n")
string(APPEND script_args "--dac_key \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid_upper}-Key.der\"\n")
string(APPEND script_args "--pai_cert \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-PAI-noPID-Cert.der\"\n")
else()
find_program(chip_cert_exe NAMES chip-cert REQUIRED)
Expand All @@ -79,6 +80,7 @@ string(APPEND script_args "--spake2_it \"${CONFIG_CHIP_DEVICE_SPAKE2_IT}\"\n")
string(APPEND script_args "--spake2_salt \"${CONFIG_CHIP_DEVICE_SPAKE2_SALT}\"\n")
string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n")
string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n")
string(APPEND script_args "--include_passcode\n")
string(APPEND script_args "--overwrite\n")

# check if spake2 verifier should be generated using script
Expand Down
39 changes: 20 additions & 19 deletions scripts/tools/telink/generate_telink_chip_factory_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,29 +171,25 @@ 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: bytes) -> dict:
""" Generate Spake2+ params using external spake2p tool
def gen_spake2p_verifier(passcode: int, it: int, salt: bytes) -> str:
""" Generate Spake2+ verifier using SPAKE2+ Python Tool

Args:
spake2p_path (str): path to spake2p executable
passcode (int): Pairing passcode using in Spake2+
it (int): Iteration counter for Spake2+ verifier generation
salt (str): Salt used to generate Spake2+ verifier

Returns:
dict: dictionary containing passcode, it, salt, and generated Verifier
verifier encoded in Base64
"""

cmd = [
spake2p_path, 'gen-verifier',
os.path.join(MATTER_ROOT, 'scripts/tools/spake2p/spake2p.py'), 'gen-verifier',
'--passcode', str(passcode),
'--salt', base64.b64encode(salt).decode('ascii'),
'--iteration-count', str(it),
'--salt', base64.b64encode(salt),
'--pin-code', str(passcode),
'--out', '-',
]
output = subprocess.check_output(cmd)
output = output.decode('utf-8').splitlines()
return dict(zip(output[0].split(','), output[1].split(',')))
return subprocess.check_output(cmd)


class FactoryDataGenerator:
Expand Down Expand Up @@ -223,8 +219,8 @@ def _validate_args(self):
self._user_data = json.loads(self._args.user)
except json.decoder.JSONDecodeError as e:
raise AssertionError("Provided wrong user data, this is not a JSON format! {}".format(e))
assert (self._args.spake2_verifier or (self._args.passcode and self._args.spake2p_path)), \
"Cannot find Spake2+ verifier, to generate a new one please provide passcode (--passcode) and path to spake2p tool (--spake2p_path)"
assert self._args.spake2_verifier or self._args.passcode, \
"Cannot find Spake2+ verifier, to generate a new one please provide passcode (--passcode)"
assert (self._args.chip_cert_path or (self._args.dac_cert and self._args.pai_cert and self._args.dac_key)), \
"Cannot find paths to DAC or PAI certificates .der files. To generate a new ones please provide a path to chip-cert executable (--chip_cert_path)"
assert self._args.output.endswith(".json"), \
Expand Down Expand Up @@ -301,6 +297,9 @@ def generate_json(self):
self._add_entry("product_id", self._args.product_id)
self._add_entry("vendor_name", self._args.vendor_name)
self._add_entry("product_name", self._args.product_name)
self._add_entry("product_label", self._args.product_label)
self._add_entry("product_url", self._args.product_url)
self._add_entry("part_number", self._args.part_number)
self._add_entry("date", self._args.date)
self._add_entry("hw_ver", self._args.hw_ver)
self._add_entry("hw_ver_str", self._args.hw_ver_str)
Expand Down Expand Up @@ -345,9 +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)
return base64.b64decode(spake2_params["Verifier"])
return base64.b64decode(gen_spake2p_verifier(self._args.passcode, self._args.spake2_it, self._args.spake2_salt))

def _generate_rotating_device_uid(self):
""" If rotating device unique ID has not been provided it should be generated """
Expand Down Expand Up @@ -438,9 +435,15 @@ def base64_str(s): return base64.b64decode(s)
the setup code. Discriminator is used during a discovery process.")

# optional keys
optional_arguments.add_argument("--product_url", type=str,
help="[string] provide link to product-specific web page")
optional_arguments.add_argument("--product_label", type=str,
help="[string] provide human-readable product label")
optional_arguments.add_argument("--part_number", type=str,
help="[string] provide human-readable product number")
optional_arguments.add_argument("--chip_cert_path", type=str,
help="Generate DAC and PAI certificates instead giving a path to .der files. This option requires a path to chip-cert executable."
"By default You can find spake2p in connectedhomeip/src/tools/chip-cert directory and build it there.")
"By default you can find chip-cert in connectedhomeip/src/tools/chip-cert directory and build it there.")
optional_arguments.add_argument("--dac_cert", type=str,
help="[.der] Provide the path to .der file containing DAC certificate.")
optional_arguments.add_argument("--dac_key", type=str,
Expand All @@ -455,8 +458,6 @@ def base64_str(s): return base64.b64decode(s)
help="[hex string] [128-bit hex-encoded] Provide the rotating device unique ID. If this argument is not provided a new rotating device id unique id will be generated.")
optional_arguments.add_argument("--passcode", type=allow_any_int,
help="[int | hex] Default PASE session passcode. (This is mandatory to generate Spake2+ verifier).")
optional_arguments.add_argument("--spake2p_path", type=str,
help="[string] Provide a path to spake2p. By default You can find spake2p in connectedhomeip/src/tools/spake2p directory and build it there.")
optional_arguments.add_argument("--spake2_verifier", type=base64_str,
help="[base64 string] Provide Spake2+ verifier without generating it.")
optional_arguments.add_argument("--enable_key", type=str,
Expand Down
43 changes: 30 additions & 13 deletions scripts/tools/telink/telink_factory_data.schema
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,28 @@
"type": "string",
"maxLength": 32
},
"product_label": {
"description": "more user-friendly human-readable product name",
"type": "string",
"maxLength": 64
},
"product_url": {
"description": "link to product-specific web page",
"type": "string",
"maxLength": 256
},
"part_number": {
"description": "human-readable vendor assigned part number",
"type": "string",
"maxLength": 32
},
"date": {
"description": "Manufacturing date according to ISO 8601 in notation YYYY-MM-DD",
"type": "string",
"format": "date"
"format": "date",
"minLength": 10,
"maxLength": 10,
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"hw_ver": {
"description": "Hardware version - integer",
Expand All @@ -75,30 +93,29 @@
"rd_uid": {
"description": "A randomly-generated 128-bit or longer octet string. Length has been expanded with 'hex:' prefix",
"type": "string",
"pattern:": "^hex:{1}",
"pattern": "^hex:([0-9A-Fa-f]{2}){16,}$",
"minLength": 20,
"minLength": 5,
"maxLength": 36
"minLength": 36
},
"dac_cert": {
"description": "DAC certificate in hex-string format",
"type": "string",
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
"minLength": 5,
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
"minLength": 6,
"maxLength": 1204
},
"dac_key": {
"description": "DAC Private Key in hex-string format",
"type": "string",
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
"pattern": "^hex:([0-9A-Fa-f]{2}){32}$",
"minLength": 68,
"maxLength": 68
},
"pai_cert": {
"description": "PAI certificate in hex-string format",
"type": "string",
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
"minLength": 5,
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
"minLength": 6,
"maxLength": 1204
},
"passcode": {
Expand All @@ -116,14 +133,14 @@
"spake2_salt": {
"description": "A key-derivation function for the Symmetric Password-Authenticated Key Exchange.",
"type": "string",
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
"minLength": 36,
"maxLength": 68
},
"spake2_verifier": {
"description": "A verifier for the Symmetric Password-Authenticated Key Exchange",
"type": "string",
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
"minLength": 97
},
"discriminator": {
Expand All @@ -135,7 +152,7 @@
"enable_key": {
"description": "The Enable Key is a 128-bit value that triggers manufacturer-specific action while invoking the TestEventTrigger Command",
"type": "string",
"pattern": "^hex:{1}([0-9A-Fa-f]){32}",
"pattern": "^hex:([0-9A-Fa-f]{2}){16}$",
"minLength": 36,
"maxLength": 36
},
Expand All @@ -144,4 +161,4 @@
"type": "object"
}
}
}
}
2 changes: 1 addition & 1 deletion src/platform/telink/CHIPDevicePlatformConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#endif

#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE CONFIG_CHIP_DEVICE_PAIRING_PASSCODE
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE
#endif

#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
Expand Down
12 changes: 12 additions & 0 deletions src/platform/telink/FactoryDataParser.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData
{
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->product_name);
}
else if (strncmp("part_number", (const char *) currentString.value, currentString.len) == 0)
{
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->part_number);
}
else if (strncmp("product_url", (const char *) currentString.value, currentString.len) == 0)
{
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->product_url);
}
else if (strncmp("product_label", (const char *) currentString.value, currentString.len) == 0)
{
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->product_label);
}
else if (strncmp("enable_key", (const char *) currentString.value, currentString.len) == 0)
{
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->enable_key);
Expand Down
3 changes: 3 additions & 0 deletions src/platform/telink/FactoryDataParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ struct FactoryData
uint16_t product_id;
struct FactoryDataString vendor_name;
struct FactoryDataString product_name;
struct FactoryDataString part_number;
struct FactoryDataString product_url;
struct FactoryDataString product_label;
uint16_t hw_ver;
struct FactoryDataString hw_ver_str;
struct FactoryDataString rd_uid;
Expand Down
60 changes: 33 additions & 27 deletions src/platform/telink/FactoryDataProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P
memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size());
return keypair.Deserialize(serializedKeypair);
}

CHIP_ERROR GetFactoryDataString(const FactoryDataString & str, char * buf, size_t bufSize)
{
ReturnErrorCodeIf(bufSize < str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!str.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);

memcpy(buf, str.data, str.len);
buf[str.len] = 0;

return CHIP_NO_ERROR;
}

} // namespace

namespace DeviceLayer {
Expand Down Expand Up @@ -230,13 +242,7 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SetSetupPasscode(uint32_t setu
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorName(char * buf, size_t bufSize)
{
ReturnErrorCodeIf(bufSize < mFactoryData.vendor_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.vendor_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);

memcpy(buf, mFactoryData.vendor_name.data, mFactoryData.vendor_name.len);
buf[mFactoryData.vendor_name.len] = 0;

return CHIP_NO_ERROR;
return GetFactoryDataString(mFactoryData.vendor_name, buf, bufSize);
}

template <class FlashFactoryData>
Expand All @@ -250,13 +256,7 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorId(uint16_t & vendorI
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductName(char * buf, size_t bufSize)
{
ReturnErrorCodeIf(bufSize < mFactoryData.product_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.product_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);

memcpy(buf, mFactoryData.product_name.data, mFactoryData.product_name.len);
buf[mFactoryData.product_name.len] = 0;

return CHIP_NO_ERROR;
return GetFactoryDataString(mFactoryData.product_name, buf, bufSize);
}

template <class FlashFactoryData>
Expand All @@ -268,15 +268,27 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductId(uint16_t & produc
}

template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSerialNumber(char * buf, size_t bufSize)
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetPartNumber(char * buf, size_t bufSize)
{
ReturnErrorCodeIf(bufSize < mFactoryData.sn.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.sn.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
return GetFactoryDataString(mFactoryData.part_number, buf, bufSize);
}

memcpy(buf, mFactoryData.sn.data, mFactoryData.sn.len);
buf[mFactoryData.sn.len] = 0;
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductURL(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.product_url, buf, bufSize);
}

return CHIP_NO_ERROR;
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductLabel(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.product_label, buf, bufSize);
}

template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSerialNumber(char * buf, size_t bufSize)
{
return GetFactoryDataString(mFactoryData.sn, buf, bufSize);
}

template <class FlashFactoryData>
Expand All @@ -300,13 +312,7 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersion(uint16_t &
template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersionString(char * buf, size_t bufSize)
{
ReturnErrorCodeIf(bufSize < mFactoryData.hw_ver_str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorCodeIf(!mFactoryData.hw_ver_str.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);

memcpy(buf, mFactoryData.hw_ver_str.data, mFactoryData.hw_ver_str.len);
buf[mFactoryData.hw_ver_str.len] = 0;

return CHIP_NO_ERROR;
return GetFactoryDataString(mFactoryData.hw_ver_str, buf, bufSize);
}

template <class FlashFactoryData>
Expand Down
3 changes: 3 additions & 0 deletions src/platform/telink/FactoryDataProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentia
CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
CHIP_ERROR GetProductId(uint16_t & productId) override;
CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override;
CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override;
CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override;
CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
Expand Down