Skip to content

Commit 2075b45

Browse files
authored
[Telink] fix factory data as pr project-chip#23385 (project-chip#23559)
1 parent 24a0371 commit 2075b45

8 files changed

+106
-62
lines changed

config/telink/chip-module/generate_factory_data.cmake

+4-2
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,11 @@ if(CONFIG_CHIP_FACTORY_DATA_USE_DEFAULT_CERTS)
6363
# convert decimal PID to its hexadecimal representation to find out certification files in repository
6464
math(EXPR LOCAL_PID "${CONFIG_CHIP_DEVICE_PRODUCT_ID}" OUTPUT_FORMAT HEXADECIMAL)
6565
string(SUBSTRING ${LOCAL_PID} 2 -1 raw_pid)
66+
string(TOUPPER ${raw_pid} raw_pid_upper)
6667
# all certs are located in ${CHIP_ROOT}/credentials/development/attestation
6768
# it can be used during development without need to generate new certifications
68-
string(APPEND script_args "--dac_cert \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid}-Cert.der\"\n")
69-
string(APPEND script_args "--dac_key \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid}-Key.der\"\n")
69+
string(APPEND script_args "--dac_cert \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid_upper}-Cert.der\"\n")
70+
string(APPEND script_args "--dac_key \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-DAC-${raw_pid_upper}-Key.der\"\n")
7071
string(APPEND script_args "--pai_cert \"${CHIP_ROOT}/credentials/development/attestation/Matter-Development-PAI-noPID-Cert.der\"\n")
7172
else()
7273
find_program(chip_cert_exe NAMES chip-cert REQUIRED)
@@ -79,6 +80,7 @@ string(APPEND script_args "--spake2_it \"${CONFIG_CHIP_DEVICE_SPAKE2_IT}\"\n")
7980
string(APPEND script_args "--spake2_salt \"${CONFIG_CHIP_DEVICE_SPAKE2_SALT}\"\n")
8081
string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n")
8182
string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n")
83+
string(APPEND script_args "--include_passcode\n")
8284
string(APPEND script_args "--overwrite\n")
8385

8486
# check if spake2 verifier should be generated using script

scripts/tools/telink/generate_telink_chip_factory_data.py

+20-19
Original file line numberDiff line numberDiff line change
@@ -171,29 +171,25 @@ def gen_test_certs(chip_cert_exe: str,
171171
new_certificates["PAI_CERT"] + ".der")
172172

173173

174-
def gen_spake2p_params(spake2p_path: str, passcode: int, it: int, salt: bytes) -> dict:
175-
""" Generate Spake2+ params using external spake2p tool
174+
def gen_spake2p_verifier(passcode: int, it: int, salt: bytes) -> str:
175+
""" Generate Spake2+ verifier using SPAKE2+ Python Tool
176176
177177
Args:
178-
spake2p_path (str): path to spake2p executable
179178
passcode (int): Pairing passcode using in Spake2+
180179
it (int): Iteration counter for Spake2+ verifier generation
181180
salt (str): Salt used to generate Spake2+ verifier
182181
183182
Returns:
184-
dict: dictionary containing passcode, it, salt, and generated Verifier
183+
verifier encoded in Base64
185184
"""
186185

187186
cmd = [
188-
spake2p_path, 'gen-verifier',
187+
os.path.join(MATTER_ROOT, 'scripts/tools/spake2p/spake2p.py'), 'gen-verifier',
188+
'--passcode', str(passcode),
189+
'--salt', base64.b64encode(salt).decode('ascii'),
189190
'--iteration-count', str(it),
190-
'--salt', base64.b64encode(salt),
191-
'--pin-code', str(passcode),
192-
'--out', '-',
193191
]
194-
output = subprocess.check_output(cmd)
195-
output = output.decode('utf-8').splitlines()
196-
return dict(zip(output[0].split(','), output[1].split(',')))
192+
return subprocess.check_output(cmd)
197193

198194

199195
class FactoryDataGenerator:
@@ -223,8 +219,8 @@ def _validate_args(self):
223219
self._user_data = json.loads(self._args.user)
224220
except json.decoder.JSONDecodeError as e:
225221
raise AssertionError("Provided wrong user data, this is not a JSON format! {}".format(e))
226-
assert (self._args.spake2_verifier or (self._args.passcode and self._args.spake2p_path)), \
227-
"Cannot find Spake2+ verifier, to generate a new one please provide passcode (--passcode) and path to spake2p tool (--spake2p_path)"
222+
assert self._args.spake2_verifier or self._args.passcode, \
223+
"Cannot find Spake2+ verifier, to generate a new one please provide passcode (--passcode)"
228224
assert (self._args.chip_cert_path or (self._args.dac_cert and self._args.pai_cert and self._args.dac_key)), \
229225
"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)"
230226
assert self._args.output.endswith(".json"), \
@@ -301,6 +297,9 @@ def generate_json(self):
301297
self._add_entry("product_id", self._args.product_id)
302298
self._add_entry("vendor_name", self._args.vendor_name)
303299
self._add_entry("product_name", self._args.product_name)
300+
self._add_entry("product_label", self._args.product_label)
301+
self._add_entry("product_url", self._args.product_url)
302+
self._add_entry("part_number", self._args.part_number)
304303
self._add_entry("date", self._args.date)
305304
self._add_entry("hw_ver", self._args.hw_ver)
306305
self._add_entry("hw_ver_str", self._args.hw_ver_str)
@@ -345,9 +344,7 @@ def _add_entry(self, name: str, value: any):
345344

346345
def _generate_spake2_verifier(self):
347346
""" If verifier has not been provided in arguments list it should be generated via external script """
348-
spake2_params = gen_spake2p_params(self._args.spake2p_path, self._args.passcode,
349-
self._args.spake2_it, self._args.spake2_salt)
350-
return base64.b64decode(spake2_params["Verifier"])
347+
return base64.b64decode(gen_spake2p_verifier(self._args.passcode, self._args.spake2_it, self._args.spake2_salt))
351348

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

440437
# optional keys
438+
optional_arguments.add_argument("--product_url", type=str,
439+
help="[string] provide link to product-specific web page")
440+
optional_arguments.add_argument("--product_label", type=str,
441+
help="[string] provide human-readable product label")
442+
optional_arguments.add_argument("--part_number", type=str,
443+
help="[string] provide human-readable product number")
441444
optional_arguments.add_argument("--chip_cert_path", type=str,
442445
help="Generate DAC and PAI certificates instead giving a path to .der files. This option requires a path to chip-cert executable."
443-
"By default You can find spake2p in connectedhomeip/src/tools/chip-cert directory and build it there.")
446+
"By default you can find chip-cert in connectedhomeip/src/tools/chip-cert directory and build it there.")
444447
optional_arguments.add_argument("--dac_cert", type=str,
445448
help="[.der] Provide the path to .der file containing DAC certificate.")
446449
optional_arguments.add_argument("--dac_key", type=str,
@@ -455,8 +458,6 @@ def base64_str(s): return base64.b64decode(s)
455458
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.")
456459
optional_arguments.add_argument("--passcode", type=allow_any_int,
457460
help="[int | hex] Default PASE session passcode. (This is mandatory to generate Spake2+ verifier).")
458-
optional_arguments.add_argument("--spake2p_path", type=str,
459-
help="[string] Provide a path to spake2p. By default You can find spake2p in connectedhomeip/src/tools/spake2p directory and build it there.")
460461
optional_arguments.add_argument("--spake2_verifier", type=base64_str,
461462
help="[base64 string] Provide Spake2+ verifier without generating it.")
462463
optional_arguments.add_argument("--enable_key", type=str,

scripts/tools/telink/telink_factory_data.schema

+30-13
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,28 @@
5555
"type": "string",
5656
"maxLength": 32
5757
},
58+
"product_label": {
59+
"description": "more user-friendly human-readable product name",
60+
"type": "string",
61+
"maxLength": 64
62+
},
63+
"product_url": {
64+
"description": "link to product-specific web page",
65+
"type": "string",
66+
"maxLength": 256
67+
},
68+
"part_number": {
69+
"description": "human-readable vendor assigned part number",
70+
"type": "string",
71+
"maxLength": 32
72+
},
5873
"date": {
5974
"description": "Manufacturing date according to ISO 8601 in notation YYYY-MM-DD",
6075
"type": "string",
61-
"format": "date"
76+
"format": "date",
77+
"minLength": 10,
78+
"maxLength": 10,
79+
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
6280
},
6381
"hw_ver": {
6482
"description": "Hardware version - integer",
@@ -75,30 +93,29 @@
7593
"rd_uid": {
7694
"description": "A randomly-generated 128-bit or longer octet string. Length has been expanded with 'hex:' prefix",
7795
"type": "string",
78-
"pattern:": "^hex:{1}",
96+
"pattern": "^hex:([0-9A-Fa-f]{2}){16,}$",
7997
"minLength": 20,
80-
"minLength": 5,
81-
"maxLength": 36
98+
"minLength": 36
8299
},
83100
"dac_cert": {
84101
"description": "DAC certificate in hex-string format",
85102
"type": "string",
86-
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
87-
"minLength": 5,
103+
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
104+
"minLength": 6,
88105
"maxLength": 1204
89106
},
90107
"dac_key": {
91108
"description": "DAC Private Key in hex-string format",
92109
"type": "string",
93-
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
110+
"pattern": "^hex:([0-9A-Fa-f]{2}){32}$",
94111
"minLength": 68,
95112
"maxLength": 68
96113
},
97114
"pai_cert": {
98115
"description": "PAI certificate in hex-string format",
99116
"type": "string",
100-
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
101-
"minLength": 5,
117+
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
118+
"minLength": 6,
102119
"maxLength": 1204
103120
},
104121
"passcode": {
@@ -116,14 +133,14 @@
116133
"spake2_salt": {
117134
"description": "A key-derivation function for the Symmetric Password-Authenticated Key Exchange.",
118135
"type": "string",
119-
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
136+
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
120137
"minLength": 36,
121138
"maxLength": 68
122139
},
123140
"spake2_verifier": {
124141
"description": "A verifier for the Symmetric Password-Authenticated Key Exchange",
125142
"type": "string",
126-
"pattern:": "^hex:{1}([0-9A-Fa-f]){2,}",
143+
"pattern": "^hex:([0-9A-Fa-f]{2})+$",
127144
"minLength": 97
128145
},
129146
"discriminator": {
@@ -135,7 +152,7 @@
135152
"enable_key": {
136153
"description": "The Enable Key is a 128-bit value that triggers manufacturer-specific action while invoking the TestEventTrigger Command",
137154
"type": "string",
138-
"pattern": "^hex:{1}([0-9A-Fa-f]){32}",
155+
"pattern": "^hex:([0-9A-Fa-f]{2}){16}$",
139156
"minLength": 36,
140157
"maxLength": 36
141158
},
@@ -144,4 +161,4 @@
144161
"type": "object"
145162
}
146163
}
147-
}
164+
}

src/platform/telink/CHIPDevicePlatformConfig.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
#endif
4141

4242
#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
43-
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE CONFIG_CHIP_DEVICE_PAIRING_PASSCODE
43+
#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE
4444
#endif
4545

4646
#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR

src/platform/telink/FactoryDataParser.c

+12
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData
149149
{
150150
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->product_name);
151151
}
152+
else if (strncmp("part_number", (const char *) currentString.value, currentString.len) == 0)
153+
{
154+
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->part_number);
155+
}
156+
else if (strncmp("product_url", (const char *) currentString.value, currentString.len) == 0)
157+
{
158+
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->product_url);
159+
}
160+
else if (strncmp("product_label", (const char *) currentString.value, currentString.len) == 0)
161+
{
162+
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->product_label);
163+
}
152164
else if (strncmp("enable_key", (const char *) currentString.value, currentString.len) == 0)
153165
{
154166
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->enable_key);

src/platform/telink/FactoryDataParser.h

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ struct FactoryData
4242
uint16_t product_id;
4343
struct FactoryDataString vendor_name;
4444
struct FactoryDataString product_name;
45+
struct FactoryDataString part_number;
46+
struct FactoryDataString product_url;
47+
struct FactoryDataString product_label;
4548
uint16_t hw_ver;
4649
struct FactoryDataString hw_ver_str;
4750
struct FactoryDataString rd_uid;

src/platform/telink/FactoryDataProvider.cpp

+33-27
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ CHIP_ERROR LoadKeypairFromRaw(ByteSpan privateKey, ByteSpan publicKey, Crypto::P
3737
memcpy(serializedKeypair.Bytes() + publicKey.size(), privateKey.data(), privateKey.size());
3838
return keypair.Deserialize(serializedKeypair);
3939
}
40+
41+
CHIP_ERROR GetFactoryDataString(const FactoryDataString & str, char * buf, size_t bufSize)
42+
{
43+
ReturnErrorCodeIf(bufSize < str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
44+
ReturnErrorCodeIf(!str.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
45+
46+
memcpy(buf, str.data, str.len);
47+
buf[str.len] = 0;
48+
49+
return CHIP_NO_ERROR;
50+
}
51+
4052
} // namespace
4153

4254
namespace DeviceLayer {
@@ -230,13 +242,7 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::SetSetupPasscode(uint32_t setu
230242
template <class FlashFactoryData>
231243
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorName(char * buf, size_t bufSize)
232244
{
233-
ReturnErrorCodeIf(bufSize < mFactoryData.vendor_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
234-
ReturnErrorCodeIf(!mFactoryData.vendor_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
235-
236-
memcpy(buf, mFactoryData.vendor_name.data, mFactoryData.vendor_name.len);
237-
buf[mFactoryData.vendor_name.len] = 0;
238-
239-
return CHIP_NO_ERROR;
245+
return GetFactoryDataString(mFactoryData.vendor_name, buf, bufSize);
240246
}
241247

242248
template <class FlashFactoryData>
@@ -250,13 +256,7 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetVendorId(uint16_t & vendorI
250256
template <class FlashFactoryData>
251257
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductName(char * buf, size_t bufSize)
252258
{
253-
ReturnErrorCodeIf(bufSize < mFactoryData.product_name.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
254-
ReturnErrorCodeIf(!mFactoryData.product_name.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
255-
256-
memcpy(buf, mFactoryData.product_name.data, mFactoryData.product_name.len);
257-
buf[mFactoryData.product_name.len] = 0;
258-
259-
return CHIP_NO_ERROR;
259+
return GetFactoryDataString(mFactoryData.product_name, buf, bufSize);
260260
}
261261

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

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

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

279-
return CHIP_NO_ERROR;
282+
template <class FlashFactoryData>
283+
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductLabel(char * buf, size_t bufSize)
284+
{
285+
return GetFactoryDataString(mFactoryData.product_label, buf, bufSize);
286+
}
287+
288+
template <class FlashFactoryData>
289+
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetSerialNumber(char * buf, size_t bufSize)
290+
{
291+
return GetFactoryDataString(mFactoryData.sn, buf, bufSize);
280292
}
281293

282294
template <class FlashFactoryData>
@@ -300,13 +312,7 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersion(uint16_t &
300312
template <class FlashFactoryData>
301313
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetHardwareVersionString(char * buf, size_t bufSize)
302314
{
303-
ReturnErrorCodeIf(bufSize < mFactoryData.hw_ver_str.len + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
304-
ReturnErrorCodeIf(!mFactoryData.hw_ver_str.data, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
305-
306-
memcpy(buf, mFactoryData.hw_ver_str.data, mFactoryData.hw_ver_str.len);
307-
buf[mFactoryData.hw_ver_str.len] = 0;
308-
309-
return CHIP_NO_ERROR;
315+
return GetFactoryDataString(mFactoryData.hw_ver_str, buf, bufSize);
310316
}
311317

312318
template <class FlashFactoryData>

src/platform/telink/FactoryDataProvider.h

+3
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentia
9494
CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
9595
CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
9696
CHIP_ERROR GetProductId(uint16_t & productId) override;
97+
CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override;
98+
CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override;
99+
CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override;
97100
CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
98101
CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
99102
CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;

0 commit comments

Comments
 (0)