Options.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. *
  3. * Copyright (c) 2020 Project CHIP Authors
  4. * All rights reserved.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include <errno.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "Options.h"
  22. #include <app/server/OnboardingCodesUtil.h>
  23. #include <crypto/CHIPCryptoPAL.h>
  24. #include <lib/core/CHIPError.h>
  25. #include <lib/support/Base64.h>
  26. #include <lib/support/BytesToHex.h>
  27. #include <lib/support/SafeInt.h>
  28. #include <credentials/examples/DeviceAttestationCredsExample.h>
  29. #if ENABLE_TRACING
  30. #include <TracingCommandLineArgument.h> // nogncheck
  31. #endif
  32. using namespace chip;
  33. using namespace chip::ArgParser;
  34. namespace {
  35. LinuxDeviceOptions gDeviceOptions;
  36. // Follow the code style of command line arguments in case we need to add more options in the future.
  37. enum
  38. {
  39. kDeviceOption_BleDevice = 0x1000,
  40. kDeviceOption_WiFi = 0x1001,
  41. kDeviceOption_Thread = 0x1002,
  42. kDeviceOption_Version = 0x1003,
  43. kDeviceOption_VendorID = 0x1004,
  44. kDeviceOption_ProductID = 0x1005,
  45. kDeviceOption_CustomFlow = 0x1006,
  46. kDeviceOption_Capabilities = 0x1007,
  47. kDeviceOption_Discriminator = 0x1008,
  48. kDeviceOption_Passcode = 0x1009,
  49. #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE || CHIP_DEVICE_ENABLE_PORT_PARAMS
  50. kDeviceOption_SecuredDevicePort = 0x100a,
  51. kDeviceOption_UnsecuredCommissionerPort = 0x100b,
  52. #endif
  53. #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
  54. kDeviceOption_SecuredCommissionerPort = 0x100c,
  55. #endif
  56. kDeviceOption_Command = 0x100d,
  57. kDeviceOption_PICS = 0x100e,
  58. kDeviceOption_KVS = 0x100f,
  59. kDeviceOption_InterfaceId = 0x1010,
  60. kDeviceOption_Spake2pVerifierBase64 = 0x1011,
  61. kDeviceOption_Spake2pSaltBase64 = 0x1012,
  62. kDeviceOption_Spake2pIterations = 0x1013,
  63. kDeviceOption_TraceFile = 0x1014,
  64. kDeviceOption_TraceLog = 0x1015,
  65. kDeviceOption_TraceDecode = 0x1016,
  66. kOptionCSRResponseCSRIncorrectType = 0x1017,
  67. kOptionCSRResponseCSRNonceIncorrectType = 0x1018,
  68. kOptionCSRResponseCSRNonceTooLong = 0x1019,
  69. kOptionCSRResponseCSRNonceInvalid = 0x101a,
  70. kOptionCSRResponseNOCSRElementsTooLong = 0x101b,
  71. kOptionCSRResponseAttestationSignatureIncorrectType = 0x101c,
  72. kOptionCSRResponseAttestationSignatureInvalid = 0x101d,
  73. kOptionCSRResponseCSRExistingKeyPair = 0x101e,
  74. kDeviceOption_TestEventTriggerEnableKey = 0x101f,
  75. kCommissionerOption_FabricID = 0x1020,
  76. kTraceTo = 0x1021,
  77. kOptionSimulateNoInternalTime = 0x1022,
  78. };
  79. constexpr unsigned kAppUsageLength = 64;
  80. OptionDef sDeviceOptionDefs[] = {
  81. #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
  82. { "ble-device", kArgumentRequired, kDeviceOption_BleDevice },
  83. #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
  84. #if CHIP_DEVICE_CONFIG_ENABLE_WIFI
  85. { "wifi", kNoArgument, kDeviceOption_WiFi },
  86. #endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
  87. #if CHIP_ENABLE_OPENTHREAD
  88. { "thread", kNoArgument, kDeviceOption_Thread },
  89. #endif // CHIP_ENABLE_OPENTHREAD
  90. { "version", kArgumentRequired, kDeviceOption_Version },
  91. { "vendor-id", kArgumentRequired, kDeviceOption_VendorID },
  92. { "product-id", kArgumentRequired, kDeviceOption_ProductID },
  93. { "custom-flow", kArgumentRequired, kDeviceOption_CustomFlow },
  94. { "capabilities", kArgumentRequired, kDeviceOption_Capabilities },
  95. { "discriminator", kArgumentRequired, kDeviceOption_Discriminator },
  96. { "passcode", kArgumentRequired, kDeviceOption_Passcode },
  97. { "spake2p-verifier-base64", kArgumentRequired, kDeviceOption_Spake2pVerifierBase64 },
  98. { "spake2p-salt-base64", kArgumentRequired, kDeviceOption_Spake2pSaltBase64 },
  99. { "spake2p-iterations", kArgumentRequired, kDeviceOption_Spake2pIterations },
  100. #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE || CHIP_DEVICE_ENABLE_PORT_PARAMS
  101. { "secured-device-port", kArgumentRequired, kDeviceOption_SecuredDevicePort },
  102. { "unsecured-commissioner-port", kArgumentRequired, kDeviceOption_UnsecuredCommissionerPort },
  103. #endif
  104. #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
  105. { "secured-commissioner-port", kArgumentRequired, kDeviceOption_SecuredCommissionerPort },
  106. #endif
  107. { "command", kArgumentRequired, kDeviceOption_Command },
  108. { "PICS", kArgumentRequired, kDeviceOption_PICS },
  109. { "KVS", kArgumentRequired, kDeviceOption_KVS },
  110. { "interface-id", kArgumentRequired, kDeviceOption_InterfaceId },
  111. #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  112. { "trace_file", kArgumentRequired, kDeviceOption_TraceFile },
  113. { "trace_log", kArgumentRequired, kDeviceOption_TraceLog },
  114. { "trace_decode", kArgumentRequired, kDeviceOption_TraceDecode },
  115. #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  116. { "cert_error_csr_incorrect_type", kNoArgument, kOptionCSRResponseCSRIncorrectType },
  117. { "cert_error_csr_existing_keypair", kNoArgument, kOptionCSRResponseCSRExistingKeyPair },
  118. { "cert_error_csr_nonce_incorrect_type", kNoArgument, kOptionCSRResponseCSRNonceIncorrectType },
  119. { "cert_error_csr_nonce_too_long", kNoArgument, kOptionCSRResponseCSRNonceTooLong },
  120. { "cert_error_csr_nonce_invalid", kNoArgument, kOptionCSRResponseCSRNonceInvalid },
  121. { "cert_error_nocsrelements_too_long", kNoArgument, kOptionCSRResponseNOCSRElementsTooLong },
  122. { "cert_error_attestation_signature_incorrect_type", kNoArgument, kOptionCSRResponseAttestationSignatureIncorrectType },
  123. { "cert_error_attestation_signature_invalid", kNoArgument, kOptionCSRResponseAttestationSignatureInvalid },
  124. { "enable-key", kArgumentRequired, kDeviceOption_TestEventTriggerEnableKey },
  125. { "commissioner-fabric-id", kArgumentRequired, kCommissionerOption_FabricID },
  126. #if ENABLE_TRACING
  127. { "trace-to", kArgumentRequired, kTraceTo },
  128. #endif
  129. { "simulate-no-internal-time", kNoArgument, kOptionSimulateNoInternalTime },
  130. {}
  131. };
  132. const char * sDeviceOptionHelp =
  133. #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
  134. " --ble-device <number>\n"
  135. " The device number for CHIPoBLE, without 'hci' prefix, can be found by hciconfig.\n"
  136. #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
  137. #if CHIP_DEVICE_CONFIG_ENABLE_WPA
  138. "\n"
  139. " --wifi\n"
  140. " Enable WiFi management via wpa_supplicant.\n"
  141. #endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
  142. #if CHIP_ENABLE_OPENTHREAD
  143. "\n"
  144. " --thread\n"
  145. " Enable Thread management via ot-agent.\n"
  146. #endif // CHIP_ENABLE_OPENTHREAD
  147. "\n"
  148. " --version <version>\n"
  149. " The version indication provides versioning of the setup payload.\n"
  150. "\n"
  151. " --vendor-id <id>\n"
  152. " The Vendor ID is assigned by the Connectivity Standards Alliance.\n"
  153. "\n"
  154. " --product-id <id>\n"
  155. " The Product ID is specified by vendor.\n"
  156. "\n"
  157. " --custom-flow <Standard = 0 | UserActionRequired = 1 | Custom = 2>\n"
  158. " A 2-bit unsigned enumeration specifying manufacturer-specific custom flow options.\n"
  159. "\n"
  160. " --capabilities <None = 0, SoftAP = 1 << 0, BLE = 1 << 1, OnNetwork = 1 << 2>\n"
  161. " Discovery Capabilities Bitmask which contains information about Device’s available technologies for device discovery.\n"
  162. "\n"
  163. " --discriminator <discriminator>\n"
  164. " A 12-bit unsigned integer match the value which a device advertises during commissioning.\n"
  165. "\n"
  166. " --passcode <passcode>\n"
  167. " A 27-bit unsigned integer, which serves as proof of possession during commissioning. \n"
  168. " If not provided to compute a verifier, the --spake2p-verifier-base64 must be provided. \n"
  169. "\n"
  170. " --spake2p-verifier-base64 <PASE verifier as base64>\n"
  171. " A raw concatenation of 'W0' and 'L' (67 bytes) as base64 to override the verifier\n"
  172. " auto-computed from the passcode, if provided.\n"
  173. "\n"
  174. " --spake2p-salt-base64 <PASE salt as base64>\n"
  175. " 16-32 bytes of salt to use for the PASE verifier, as base64. If omitted, will be generated\n"
  176. " randomly. If a --spake2p-verifier-base64 is passed, it must match against the salt otherwise\n"
  177. " failure will arise.\n"
  178. "\n"
  179. " --spake2p-iterations <PASE PBKDF iterations>\n"
  180. " Number of PBKDF iterations to use. If omitted, will be 1000. If a --spake2p-verifier-base64 is\n"
  181. " passed, the iteration counts must match that used to generate the verifier otherwise failure will\n"
  182. " arise.\n"
  183. "\n"
  184. #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE || CHIP_DEVICE_ENABLE_PORT_PARAMS
  185. " --secured-device-port <port>\n"
  186. " A 16-bit unsigned integer specifying the listen port to use for secure device messages (default is 5540).\n"
  187. "\n"
  188. " --unsecured-commissioner-port <port>\n"
  189. " A 16-bit unsigned integer specifying the port to use for unsecured commissioner messages (default is 5550).\n"
  190. "\n"
  191. #endif
  192. #if CHIP_DEVICE_ENABLE_PORT_PARAMS
  193. " --secured-commissioner-port <port>\n"
  194. " A 16-bit unsigned integer specifying the listen port to use for secure commissioner messages (default is 5552). Only "
  195. "valid when app is both device and commissioner\n"
  196. "\n"
  197. #endif
  198. " --commissioner-fabric-id <fabricid>\n"
  199. " The fabric ID to be used when this device is a commissioner (default in code is 1).\n"
  200. "\n"
  201. " --command <command-name>\n"
  202. " A name for a command to execute during startup.\n"
  203. "\n"
  204. " --PICS <filepath>\n"
  205. " A file containing PICS items.\n"
  206. "\n"
  207. " --KVS <filepath>\n"
  208. " A file to store Key Value Store items.\n"
  209. "\n"
  210. " --interface-id <interface>\n"
  211. " A interface id to advertise on.\n"
  212. #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  213. "\n"
  214. " --trace_file <file>\n"
  215. " Output trace data to the provided file.\n"
  216. " --trace_log <1/0>\n"
  217. " A value of 1 enables traces to go to the log, 0 disables this (default 0).\n"
  218. " --trace_decode <1/0>\n"
  219. " A value of 1 enables traces decoding, 0 disables this (default 0).\n"
  220. #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  221. " --cert_error_csr_incorrect_type\n"
  222. " Configure the CSRResponse to be built with an invalid CSR type.\n"
  223. " --cert_error_csr_existing_keypair\n"
  224. " Configure the CSRResponse to be built with a CSR where the keypair already exists.\n"
  225. " --cert_error_csr_nonce_incorrect_type\n"
  226. " Configure the CSRResponse to be built with an invalid CSRNonce type.\n"
  227. " --cert_error_csr_nonce_too_long\n"
  228. " Configure the CSRResponse to be built with a CSRNonce that is longer than expected.\n"
  229. " --cert_error_csr_nonce_invalid\n"
  230. " Configure the CSRResponse to be built with a CSRNonce that does not match the CSRNonce from the CSRRequest.\n"
  231. " --cert_error_nocsrelements_too_long\n"
  232. " Configure the CSRResponse to contains an NOCSRElements larger than the allowed RESP_MAX.\n"
  233. " --cert_error_attestation_signature_incorrect_type\n"
  234. " Configure the CSRResponse to be build with an invalid AttestationSignature type.\n"
  235. " --cert_error_attestation_signature_invalid\n"
  236. " Configure the CSRResponse to be build with an AttestationSignature that does not match what is expected.\n"
  237. " --enable-key <key>\n"
  238. " A 16-byte, hex-encoded key, used to validate TestEventTrigger command of Generial Diagnostics cluster\n"
  239. #if ENABLE_TRACING
  240. " --trace-to <destination>\n"
  241. " Trace destinations, comma separated (" SUPPORTED_COMMAND_LINE_TRACING_TARGETS ")\n"
  242. #endif
  243. " --simulate-no-internal-time\n"
  244. " Time cluster does not use internal platform time\n"
  245. "\n";
  246. bool Base64ArgToVector(const char * arg, size_t maxSize, std::vector<uint8_t> & outVector)
  247. {
  248. size_t maxBase64Size = BASE64_ENCODED_LEN(maxSize);
  249. outVector.resize(maxSize);
  250. size_t argLen = strlen(arg);
  251. VerifyOrReturnValue(argLen <= maxBase64Size, false);
  252. VerifyOrReturnValue(chip::CanCastTo<uint32_t>(argLen), false);
  253. size_t decodedLen = chip::Base64Decode32(arg, static_cast<uint32_t>(argLen), reinterpret_cast<uint8_t *>(outVector.data()));
  254. VerifyOrReturnValue(decodedLen != 0, false);
  255. outVector.resize(decodedLen);
  256. return true;
  257. }
  258. bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue)
  259. {
  260. bool retval = true;
  261. switch (aIdentifier)
  262. {
  263. case kDeviceOption_BleDevice:
  264. if (!ParseInt(aValue, LinuxDeviceOptions::GetInstance().mBleDevice))
  265. {
  266. PrintArgError("%s: invalid value specified for ble device number: %s\n", aProgram, aValue);
  267. retval = false;
  268. }
  269. break;
  270. case kDeviceOption_WiFi:
  271. LinuxDeviceOptions::GetInstance().mWiFi = true;
  272. break;
  273. case kDeviceOption_Thread:
  274. LinuxDeviceOptions::GetInstance().mThread = true;
  275. break;
  276. case kDeviceOption_Version:
  277. LinuxDeviceOptions::GetInstance().payload.version = static_cast<uint8_t>(atoi(aValue));
  278. break;
  279. case kDeviceOption_VendorID:
  280. LinuxDeviceOptions::GetInstance().payload.vendorID = static_cast<uint16_t>(atoi(aValue));
  281. break;
  282. case kDeviceOption_ProductID:
  283. LinuxDeviceOptions::GetInstance().payload.productID = static_cast<uint16_t>(atoi(aValue));
  284. break;
  285. case kDeviceOption_CustomFlow:
  286. LinuxDeviceOptions::GetInstance().payload.commissioningFlow = static_cast<CommissioningFlow>(atoi(aValue));
  287. break;
  288. case kDeviceOption_Capabilities:
  289. LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.Emplace().SetRaw(static_cast<uint8_t>(atoi(aValue)));
  290. break;
  291. case kDeviceOption_Discriminator: {
  292. uint16_t value = static_cast<uint16_t>(atoi(aValue));
  293. if (value >= 4096)
  294. {
  295. PrintArgError("%s: invalid value specified for discriminator: %s\n", aProgram, aValue);
  296. retval = false;
  297. }
  298. else
  299. {
  300. LinuxDeviceOptions::GetInstance().discriminator.SetValue(value);
  301. }
  302. break;
  303. }
  304. case kDeviceOption_Passcode:
  305. LinuxDeviceOptions::GetInstance().payload.setUpPINCode = static_cast<uint32_t>(atoi(aValue));
  306. break;
  307. case kDeviceOption_Spake2pSaltBase64: {
  308. constexpr size_t kMaxSize = chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length;
  309. std::vector<uint8_t> saltVector;
  310. bool success = Base64ArgToVector(aValue, kMaxSize, saltVector);
  311. if (!success)
  312. {
  313. PrintArgError("%s: ERROR: Base64 format for argument %s was invalid\n", aProgram, aName);
  314. retval = false;
  315. break;
  316. }
  317. if ((saltVector.size() < chip::Crypto::kSpake2p_Min_PBKDF_Salt_Length) ||
  318. (saltVector.size() > chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length))
  319. {
  320. PrintArgError("%s: ERROR: argument %s not in range [%u, %u]\n", aProgram, aName,
  321. chip::Crypto::kSpake2p_Min_PBKDF_Salt_Length, chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length);
  322. retval = false;
  323. break;
  324. }
  325. LinuxDeviceOptions::GetInstance().spake2pSalt.SetValue(std::move(saltVector));
  326. break;
  327. }
  328. case kDeviceOption_Spake2pVerifierBase64: {
  329. constexpr size_t kMaxSize = chip::Crypto::kSpake2p_VerifierSerialized_Length;
  330. std::vector<uint8_t> serializedVerifier;
  331. bool success = Base64ArgToVector(aValue, kMaxSize, serializedVerifier);
  332. if (!success)
  333. {
  334. PrintArgError("%s: ERROR: Base64 format for argument %s was invalid\n", aProgram, aName);
  335. retval = false;
  336. break;
  337. }
  338. if (serializedVerifier.size() != chip::Crypto::kSpake2p_VerifierSerialized_Length)
  339. {
  340. PrintArgError("%s: ERROR: argument %s should contain base64 for a %u bytes octet string \n", aProgram, aName,
  341. chip::Crypto::kSpake2p_VerifierSerialized_Length);
  342. retval = false;
  343. break;
  344. }
  345. LinuxDeviceOptions::GetInstance().spake2pVerifier.SetValue(std::move(serializedVerifier));
  346. break;
  347. }
  348. case kDeviceOption_Spake2pIterations: {
  349. errno = 0;
  350. uint32_t iterCount = static_cast<uint32_t>(strtoul(aValue, nullptr, 0));
  351. if (errno == ERANGE)
  352. {
  353. PrintArgError("%s: ERROR: argument %s was not parsable as an integer\n", aProgram, aName);
  354. retval = false;
  355. break;
  356. }
  357. if ((iterCount < chip::Crypto::kSpake2p_Min_PBKDF_Iterations) || (iterCount > chip::Crypto::kSpake2p_Max_PBKDF_Iterations))
  358. {
  359. PrintArgError("%s: ERROR: argument %s not in range [%u, %u]\n", aProgram, aName,
  360. chip::Crypto::kSpake2p_Min_PBKDF_Iterations, chip::Crypto::kSpake2p_Max_PBKDF_Iterations);
  361. retval = false;
  362. break;
  363. }
  364. LinuxDeviceOptions::GetInstance().spake2pIterations = iterCount;
  365. break;
  366. }
  367. #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE || CHIP_DEVICE_ENABLE_PORT_PARAMS
  368. case kDeviceOption_SecuredDevicePort:
  369. LinuxDeviceOptions::GetInstance().securedDevicePort = static_cast<uint16_t>(atoi(aValue));
  370. break;
  371. case kDeviceOption_UnsecuredCommissionerPort:
  372. LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort = static_cast<uint16_t>(atoi(aValue));
  373. break;
  374. #endif
  375. #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
  376. case kDeviceOption_SecuredCommissionerPort:
  377. LinuxDeviceOptions::GetInstance().securedCommissionerPort = static_cast<uint16_t>(atoi(aValue));
  378. break;
  379. #endif
  380. case kDeviceOption_Command:
  381. LinuxDeviceOptions::GetInstance().command = aValue;
  382. break;
  383. case kDeviceOption_PICS:
  384. LinuxDeviceOptions::GetInstance().PICS = aValue;
  385. break;
  386. case kDeviceOption_KVS:
  387. LinuxDeviceOptions::GetInstance().KVS = aValue;
  388. break;
  389. case kDeviceOption_InterfaceId:
  390. LinuxDeviceOptions::GetInstance().interfaceId =
  391. Inet::InterfaceId(static_cast<chip::Inet::InterfaceId::PlatformType>(atoi(aValue)));
  392. break;
  393. #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  394. case kDeviceOption_TraceFile:
  395. LinuxDeviceOptions::GetInstance().traceStreamFilename.SetValue(std::string{ aValue });
  396. break;
  397. case kDeviceOption_TraceLog:
  398. if (atoi(aValue) != 0)
  399. {
  400. LinuxDeviceOptions::GetInstance().traceStreamToLogEnabled = true;
  401. }
  402. break;
  403. case kDeviceOption_TraceDecode:
  404. if (atoi(aValue) != 0)
  405. {
  406. LinuxDeviceOptions::GetInstance().traceStreamDecodeEnabled = true;
  407. }
  408. break;
  409. #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  410. case kOptionCSRResponseCSRIncorrectType:
  411. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrIncorrectType = true;
  412. break;
  413. case kOptionCSRResponseCSRExistingKeyPair:
  414. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrExistingKeyPair = true;
  415. break;
  416. case kOptionCSRResponseCSRNonceIncorrectType:
  417. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceIncorrectType = true;
  418. break;
  419. case kOptionCSRResponseCSRNonceTooLong:
  420. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceTooLong = true;
  421. break;
  422. case kOptionCSRResponseCSRNonceInvalid:
  423. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrNonceInvalid = true;
  424. break;
  425. case kOptionCSRResponseNOCSRElementsTooLong:
  426. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.nocsrElementsTooLong = true;
  427. break;
  428. case kOptionCSRResponseAttestationSignatureIncorrectType:
  429. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.attestationSignatureIncorrectType = true;
  430. break;
  431. case kOptionCSRResponseAttestationSignatureInvalid:
  432. LinuxDeviceOptions::GetInstance().mCSRResponseOptions.attestationSignatureInvalid = true;
  433. break;
  434. case kDeviceOption_TestEventTriggerEnableKey: {
  435. constexpr size_t kEnableKeyLength = sizeof(LinuxDeviceOptions::GetInstance().testEventTriggerEnableKey);
  436. if (Encoding::HexToBytes(aValue, strlen(aValue), LinuxDeviceOptions::GetInstance().testEventTriggerEnableKey,
  437. kEnableKeyLength) != kEnableKeyLength)
  438. {
  439. PrintArgError("%s: ERROR: invalid value specified for %s\n", aProgram, aName);
  440. retval = false;
  441. }
  442. break;
  443. }
  444. case kCommissionerOption_FabricID: {
  445. char * eptr;
  446. LinuxDeviceOptions::GetInstance().commissionerFabricId = (chip::FabricId) strtoull(aValue, &eptr, 0);
  447. break;
  448. }
  449. #if ENABLE_TRACING
  450. case kTraceTo:
  451. LinuxDeviceOptions::GetInstance().traceTo.push_back(aValue);
  452. break;
  453. #endif
  454. case kOptionSimulateNoInternalTime:
  455. LinuxDeviceOptions::GetInstance().mSimulateNoInternalTime = true;
  456. break;
  457. default:
  458. PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName);
  459. retval = false;
  460. break;
  461. }
  462. return (retval);
  463. }
  464. OptionSet sDeviceOptions = { HandleOption, sDeviceOptionDefs, "GENERAL OPTIONS", sDeviceOptionHelp };
  465. OptionSet * sLinuxDeviceOptionSets[] = { &sDeviceOptions, nullptr, nullptr, nullptr };
  466. } // namespace
  467. CHIP_ERROR ParseArguments(int argc, char * const argv[], OptionSet * customOptions)
  468. {
  469. // Index 0 is for the general Linux options
  470. uint8_t optionSetIndex = 1;
  471. if (customOptions != nullptr)
  472. {
  473. // If there are custom options, include it during arg parsing
  474. sLinuxDeviceOptionSets[optionSetIndex++] = customOptions;
  475. }
  476. char usage[kAppUsageLength];
  477. snprintf(usage, kAppUsageLength, "Usage: %s [options]", argv[0]);
  478. HelpOptions helpOptions(argv[0], usage, "1.0");
  479. sLinuxDeviceOptionSets[optionSetIndex] = &helpOptions;
  480. if (!ParseArgs(argv[0], argc, argv, sLinuxDeviceOptionSets))
  481. {
  482. return CHIP_ERROR_INVALID_ARGUMENT;
  483. }
  484. return CHIP_NO_ERROR;
  485. }
  486. LinuxDeviceOptions & LinuxDeviceOptions::GetInstance()
  487. {
  488. if (gDeviceOptions.dacProvider == nullptr)
  489. {
  490. gDeviceOptions.dacProvider = chip::Credentials::Examples::GetExampleDACProvider();
  491. }
  492. return gDeviceOptions;
  493. }