From 5c6a3511ff0600526998b7189f3904c83991827f Mon Sep 17 00:00:00 2001 From: Bhaskar Sarma Date: Mon, 9 Mar 2020 23:45:44 -0700 Subject: [PATCH 1/7] Implement a QRCode payload generator --- src/Makefile | 2 +- src/qrcode/Makefile | 28 +++++ src/qrcode/SetupCodeUtils.cpp | 82 +++++++++++++ src/qrcode/SetupCodeUtils.h | 36 ++++++ src/qrcode/SetupPayload.h | 46 +++++++ src/qrcode/SetupPayloadGenerator.cpp | 172 +++++++++++++++++++++++++++ src/qrcode/SetupPayloadGenerator.h | 90 ++++++++++++++ src/qrcode/tests/tests.cpp | 88 ++++++++++++++ 8 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 src/qrcode/Makefile create mode 100644 src/qrcode/SetupCodeUtils.cpp create mode 100644 src/qrcode/SetupCodeUtils.h create mode 100644 src/qrcode/SetupPayload.h create mode 100644 src/qrcode/SetupPayloadGenerator.cpp create mode 100644 src/qrcode/SetupPayloadGenerator.h create mode 100644 src/qrcode/tests/tests.cpp diff --git a/src/Makefile b/src/Makefile index 61d1c39cdd91d9..499ff8f4462415 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ TOPTARGETS := all clean check -SUBDIRS = lwip system lib/core lib/support ble inet +SUBDIRS = lwip system lib/core lib/support ble inet qrcode $(TOPTARGETS): $(SUBDIRS) $(SUBDIRS): diff --git a/src/qrcode/Makefile b/src/qrcode/Makefile new file mode 100644 index 00000000000000..422526e61da0c7 --- /dev/null +++ b/src/qrcode/Makefile @@ -0,0 +1,28 @@ +TOP_DIR = ../.. +Test_Dir = tests + +.PHONY: all clean run_tests + +all: run_tests + +include $(TOP_DIR)/.yams/cpp_rules.min + +Module_Includes = \ + -I. \ + -I$(TOP_DIR)/src/include \ + -I$(TOP_DIR)/src/lib/ \ + -I$(TOP_DIR)/build/config/standalone/ + +Module_Test_Includes = $(Module_Includes) + +CPP_Files = \ + SetupCodeUtils.cpp \ + SetupPayloadGenerator.cpp \ + +libqr.a: $(CPP_Objects) + ar rvs $@ $^ + @echo "LINK => $@" + +clean: my_clean + @rm -f $(LIB_NAME) *.gcda *.gcno *.gcov + diff --git a/src/qrcode/SetupCodeUtils.cpp b/src/qrcode/SetupCodeUtils.cpp new file mode 100644 index 00000000000000..545bd20c8109e3 --- /dev/null +++ b/src/qrcode/SetupCodeUtils.cpp @@ -0,0 +1,82 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file implements converting an input into a Base45 String + * + */ + +#include "SetupCodeUtils.h" + +#include +#include + +using namespace std; + +namespace chip { + +map base45CharacterMap() +{ + map characterMap; + // Special characters + characterMap[36] = ' '; + characterMap[37] = '$'; + characterMap[38] = '%'; + characterMap[39] = '*'; + characterMap[40] = '+'; + characterMap[41] = '-'; + characterMap[42] = '.'; + characterMap[43] = '/'; + characterMap[44] = ':'; + + return characterMap; +} + +string base45EncodedString(uint64_t input, size_t minLength) +{ + static std::map BS45_CHARS = base45CharacterMap(); + string result; + int radix = 45; + do { + int remainder = input % radix; + char base45char; + if (remainder >= 0 && remainder <= 9) { + // Numbers + base45char = '0' + remainder; + } + else if (remainder >= 10 && remainder <= 35) { + // Uppercase Characters + base45char = 'A' + (remainder - 10); + } + else { + // Special Characters + base45char = BS45_CHARS[remainder]; + } + result += base45char; + input = input / radix; + } while (input != 0); + + while (result.length() < minLength) { + result.append("0"); + } + + reverse(result.begin(), result.end()); + return result; +} + +} // namespace chip diff --git a/src/qrcode/SetupCodeUtils.h b/src/qrcode/SetupCodeUtils.h new file mode 100644 index 00000000000000..ba4ad9b2301abb --- /dev/null +++ b/src/qrcode/SetupCodeUtils.h @@ -0,0 +1,36 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Utility header to encode an input into a Base45 String + */ + +#ifndef _SETUP_CODE_UTILS_H_ +#define _SETUP_CODE_UTILS_H_ + +#include + +using namespace std; + +namespace chip { + +std::string base45EncodedString(uint64_t input, size_t minLength); + +} // namespace chip + +#endif /* _SETUP_CODE_UTILS_H_ */ \ No newline at end of file diff --git a/src/qrcode/SetupPayload.h b/src/qrcode/SetupPayload.h new file mode 100644 index 00000000000000..b49ca5ec800bb9 --- /dev/null +++ b/src/qrcode/SetupPayload.h @@ -0,0 +1,46 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file describes a QRCode Setup Payload class to hold + * data enumerated from a byte stream + */ + + +#ifndef _SETUP_PAYLOAD_H_ +#define _SETUP_PAYLOAD_H_ + +#include + +namespace chip { + +class SetupPayload +{ + public: + uint8_t version; + uint16_t vendorID; + uint16_t productID; + uint8_t requiresCustomFlow; + uint16_t rendezvousInformation; + uint16_t discriminator; + uint32_t setUpPINCode; +}; + +}; // namespace chip + +#endif /* _SETUP_PAYLOAD_H_ */ \ No newline at end of file diff --git a/src/qrcode/SetupPayloadGenerator.cpp b/src/qrcode/SetupPayloadGenerator.cpp new file mode 100644 index 00000000000000..42cfd7e6dde618 --- /dev/null +++ b/src/qrcode/SetupPayloadGenerator.cpp @@ -0,0 +1,172 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file implements a QRCode Setup Payload generator in accordance + * with the CHIP specification. + * + */ + +#include "SetupPayloadGenerator.h" +#include "SetupCodeUtils.h" + +#include +#include + +using namespace chip; +using namespace std; + +void SetupPayloadGenerator::resetBitSet() +{ + mPayloadBitsIndex = kTotalPayloadDataSizeInBits; + mPayloadBits.reset(); +} + +// Populates numberOfBits starting from LSB of input into mPayloadBits +void SetupPayloadGenerator::populateInteger(uint64_t input, size_t numberOfBits) +{ + int numberOfBitsModified = 0; + + mPayloadBitsIndex -= numberOfBits; + int currentIndex = mPayloadBitsIndex; + + int endIndex = currentIndex + (numberOfBits - 1); + + int itercount = 1; + while (currentIndex <= endIndex) { + itercount++; + input & 1 ? mPayloadBits.set(currentIndex) : mPayloadBits.reset(currentIndex); + currentIndex++; + input /= 2; + } +} + +void SetupPayloadGenerator::populateVersion() +{ + populateInteger(mPayload.version, kVersionFieldLengthInBits); +} + +void SetupPayloadGenerator::populateVendorID() +{ + populateInteger(mPayload.vendorID, kVendorIDFieldLengthInBits); +} + +void SetupPayloadGenerator::populateProductID() +{ + populateInteger(mPayload.productID, kProductIDFieldLengthInBits); +} + +void SetupPayloadGenerator::populateCustomFlowRequiredField() +{ + populateInteger(mPayload.requiresCustomFlow, kCustomFlowRequiredFieldLengthInBits); +} + +void SetupPayloadGenerator::populateRendezVousInfo() +{ + populateInteger(mPayload.rendezvousInformation, kRendezvousInfoFieldLengthInBits); +} + +void SetupPayloadGenerator::populateDiscriminator() +{ + populateInteger(mPayload.discriminator, kPayloadDiscriminatorFieldLengthInBits); +} + +void SetupPayloadGenerator::populateSetupPIN() +{ + populateInteger(mPayload.setUpPINCode, kSetupPINCodeFieldLengthInBits); +} + +void SetupPayloadGenerator::populateReservedField() +{ + populateInteger(0, kReservedFieldLengthInBits); +} + +void SetupPayloadGenerator::generateBitSet() +{ + resetBitSet(); + populateVersion(); + populateVendorID(); + populateProductID(); + populateCustomFlowRequiredField(); + populateRendezVousInfo(); + populateDiscriminator(); + populateSetupPIN(); + populateReservedField(); +} + +string SetupPayloadGenerator::payloadBinaryRepresentation() +{ + generateBitSet(); + return mPayloadBits.to_string(); +} + +// This function assumes bits.size() % 8 == 0 +// TODO: Can this method be written in a more elegant way? +vector arrayFromBits(bitset bits) +{ + vector resultVector; + size_t numberOfBits = bits.size(); + size_t numberOfBytes = numberOfBits / 8; + bool oddNumOfBytes = (numberOfBytes % 2) ? true : false; + + // Traversing in reverse, hence startIndex > endIndex + int endIndex = 0; + int startIndex = bits.size() - 1; + + /* + Every 2 bytes (16 bits) of binary source data are encoded to 3 characters of the Base-45 alphabet. + If an odd number of bytes are to be encoded, the remaining single byte will be encoded + to 2 characters of the Base-45 alphabet. + */ + if (oddNumOfBytes) { + endIndex = 8; + } + + while (startIndex > endIndex) { + int currentIntegerIndex = startIndex; + uint16_t result = 0; + for (int i = currentIntegerIndex; i > currentIntegerIndex - 16; i--) { + result = result << 1; + result = result | bits.test(i); + } + resultVector.push_back(result); + startIndex -= 16; + } + + // If we have odd number of bytes append the last byte. + if (oddNumOfBytes) { + uint16_t result = 0; + for (int i = 7; i >= 0 ; i--) { + result = result << 1; + result = result & bits.test(i); + } + resultVector.push_back(result); + } + return resultVector; +} + +string SetupPayloadGenerator::payloadBase45Representation() +{ + generateBitSet(); + vector integerArray = arrayFromBits(mPayloadBits); + string result; + for (int idx = 0; idx < integerArray.size(); idx++) { + result += base45EncodedString(integerArray[idx], 3); + } + return result; +} diff --git a/src/qrcode/SetupPayloadGenerator.h b/src/qrcode/SetupPayloadGenerator.h new file mode 100644 index 00000000000000..99c88fd5eb37b8 --- /dev/null +++ b/src/qrcode/SetupPayloadGenerator.h @@ -0,0 +1,90 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file describes a QRCode Setup Payload generator based on the + * CHIP specification. + * + * The encoding of the binary data to a base45 string is as follows: + * - Every 2 bytes (16 bits) of binary source data are encoded to 3 + * characters of the Base-45 alphabet. + * - If an odd number of bytes are to be encoded, the remaining + * single byte is encoded to 2 characters of the Base-45 alphabet. + */ + +#include "SetupPayload.h" + +#include +#include +using namespace std; + +#ifndef _SETUP_PAYLOAD_GENERATOR_ +#define _SETUP_PAYLOAD_GENERATOR_ + +const int kVersionFieldLengthInBits = 3; +const int kVendorIDFieldLengthInBits = 16; +const int kProductIDFieldLengthInBits = 16; +const int kCustomFlowRequiredFieldLengthInBits = 1; +const int kRendezvousInfoFieldLengthInBits = 8; +const int kPayloadDiscriminatorFieldLengthInBits = 8; +const int kSetupPINCodeFieldLengthInBits = 27; +const int kReservedFieldLengthInBits = 1; + + +const int kTotalPayloadDataSizeInBits = ( kVersionFieldLengthInBits + \ + kVendorIDFieldLengthInBits + \ + kProductIDFieldLengthInBits + \ + kCustomFlowRequiredFieldLengthInBits + + kRendezvousInfoFieldLengthInBits + \ + kPayloadDiscriminatorFieldLengthInBits + \ + kSetupPINCodeFieldLengthInBits + \ + kReservedFieldLengthInBits + ); + +namespace chip { + +class SetupPayloadGenerator +{ + private: + bitset mPayloadBits; + SetupPayload mPayload; + // points to the current index within the bitset + int mPayloadBitsIndex; + + void populateInteger(uint64_t input, size_t numberOfBits); + void populateVersion(); + void populateVendorID(); + void populateProductID(); + void populateCustomFlowRequiredField(); + void populateRendezVousInfo(); + void populateDiscriminator(); + void populateSetupPIN(); + void populateReservedField(); + void resetBitSet(); + void generateBitSet(); + + public: + string payloadBinaryRepresentation(); + string payloadBase45Representation(); + SetupPayloadGenerator(SetupPayload setupPayload) : mPayload(setupPayload) {}; + +}; + +}; // namespace chip + +#endif /* _SETUP_PAYLOAD_GENERATOR_ */ \ No newline at end of file diff --git a/src/qrcode/tests/tests.cpp b/src/qrcode/tests/tests.cpp new file mode 100644 index 00000000000000..e9719ff2755bcc --- /dev/null +++ b/src/qrcode/tests/tests.cpp @@ -0,0 +1,88 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "SetupCodeUtils.cpp" +#include "SetupPayload.h" +#include "SetupPayloadGenerator.cpp" + +using namespace chip; +using namespace std; + +void testPayloadByteArrayRep() { + printf("---Running Test--- %s\n", __FUNCTION__); + SetupPayload payload; + + payload.version = 5; + payload.vendorID = 12; + payload.productID = 1; + payload.requiresCustomFlow = 0; + payload.rendezvousInformation = 1; + payload.discriminator = 128; + payload.setUpPINCode = 2048; + + SetupPayloadGenerator generator(payload); + string result = generator.payloadBinaryRepresentation(); + string expectedResult = + "101000000000000110000000000000000010000000011000000000000000000000010000" + "00000000"; + + assert(result.compare(expectedResult) == 0); +} + +void testPayloadBase45Rep() { + printf("---Running Test--- %s\n", __FUNCTION__); + SetupPayload payload; + + payload.version = 5; + payload.vendorID = 12; + payload.productID = 1; + payload.requiresCustomFlow = 0; + payload.rendezvousInformation = 1; + payload.discriminator = 128; + payload.setUpPINCode = 2048; + + SetupPayloadGenerator generator(payload); + string result = generator.payloadBase45Representation(); + string expectedResult = "KABG8842Q000211"; + + assert(result.compare(expectedResult) == 0); +} + +void testBase45Encoding() { + printf("---Running Test--- %s\n", __FUNCTION__); + uint16_t input = 10; + string result = base45EncodedString(input, 3); + string expectedResult = "00A"; + assert(result.compare(expectedResult) == 0); +} + +void testBitsetLen() { + printf("---Running Test--- %s\n", __FUNCTION__); + assert(kTotalPayloadDataSizeInBits % 8 == 0); +} + +int main(int argc, char** argv) { + printf("---Running Test--- tests from %s\n", __FILE__); + testBitsetLen(); + testPayloadByteArrayRep(); + testPayloadBase45Rep(); + testBase45Encoding(); +} \ No newline at end of file From 5cab0f2f8892c95c0552a0219c067c08c8177e97 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Thu, 12 Mar 2020 15:41:15 -0400 Subject: [PATCH 2/7] Define the entire Base45 CharacterSet instead of using a Map --- src/qrcode/SetupCodeUtils.cpp | 39 +++++++---------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/src/qrcode/SetupCodeUtils.cpp b/src/qrcode/SetupCodeUtils.cpp index 545bd20c8109e3..e791c74f4a5222 100644 --- a/src/qrcode/SetupCodeUtils.cpp +++ b/src/qrcode/SetupCodeUtils.cpp @@ -23,50 +23,27 @@ #include "SetupCodeUtils.h" -#include #include using namespace std; namespace chip { -map base45CharacterMap() +char base45CharacterSet[45] = { - map characterMap; - // Special characters - characterMap[36] = ' '; - characterMap[37] = '$'; - characterMap[38] = '%'; - characterMap[39] = '*'; - characterMap[40] = '+'; - characterMap[41] = '-'; - characterMap[42] = '.'; - characterMap[43] = '/'; - characterMap[44] = ':'; - - return characterMap; -} + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', + '+', '-', '.', '/', ':' +}; string base45EncodedString(uint64_t input, size_t minLength) { - static std::map BS45_CHARS = base45CharacterMap(); string result; int radix = 45; do { - int remainder = input % radix; - char base45char; - if (remainder >= 0 && remainder <= 9) { - // Numbers - base45char = '0' + remainder; - } - else if (remainder >= 10 && remainder <= 35) { - // Uppercase Characters - base45char = 'A' + (remainder - 10); - } - else { - // Special Characters - base45char = BS45_CHARS[remainder]; - } + char base45char = base45CharacterSet[input % radix]; result += base45char; input = input / radix; } while (input != 0); From 788dfd47351282444d16834d28a4d7f8eee4b9f1 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Mon, 16 Mar 2020 10:57:05 -0700 Subject: [PATCH 3/7] Refactor to correctly organize files and classes --- src/Makefile | 2 +- src/qrcode/tests/tests.cpp | 88 ------------------ src/{qrcode => setup_payload}/Makefile | 8 +- .../QRCodeSetupPayloadGenerator.cpp} | 63 +++++++------ .../QRCodeSetupPayloadGenerator.h} | 6 +- .../SetupCodeUtils.cpp | 17 ++-- .../SetupCodeUtils.h | 0 src/{qrcode => setup_payload}/SetupPayload.h | 0 src/setup_payload/tests/tests.cpp | 92 +++++++++++++++++++ 9 files changed, 141 insertions(+), 135 deletions(-) delete mode 100644 src/qrcode/tests/tests.cpp rename src/{qrcode => setup_payload}/Makefile (75%) rename src/{qrcode/SetupPayloadGenerator.cpp => setup_payload/QRCodeSetupPayloadGenerator.cpp} (73%) rename src/{qrcode/SetupPayloadGenerator.h => setup_payload/QRCodeSetupPayloadGenerator.h} (94%) rename src/{qrcode => setup_payload}/SetupCodeUtils.cpp (75%) rename src/{qrcode => setup_payload}/SetupCodeUtils.h (100%) rename src/{qrcode => setup_payload}/SetupPayload.h (100%) create mode 100644 src/setup_payload/tests/tests.cpp diff --git a/src/Makefile b/src/Makefile index 499ff8f4462415..b82cfa3326e498 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ TOPTARGETS := all clean check -SUBDIRS = lwip system lib/core lib/support ble inet qrcode +SUBDIRS = lwip system lib/core lib/support ble inet setup_payload $(TOPTARGETS): $(SUBDIRS) $(SUBDIRS): diff --git a/src/qrcode/tests/tests.cpp b/src/qrcode/tests/tests.cpp deleted file mode 100644 index e9719ff2755bcc..00000000000000 --- a/src/qrcode/tests/tests.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include - -#include "SetupCodeUtils.cpp" -#include "SetupPayload.h" -#include "SetupPayloadGenerator.cpp" - -using namespace chip; -using namespace std; - -void testPayloadByteArrayRep() { - printf("---Running Test--- %s\n", __FUNCTION__); - SetupPayload payload; - - payload.version = 5; - payload.vendorID = 12; - payload.productID = 1; - payload.requiresCustomFlow = 0; - payload.rendezvousInformation = 1; - payload.discriminator = 128; - payload.setUpPINCode = 2048; - - SetupPayloadGenerator generator(payload); - string result = generator.payloadBinaryRepresentation(); - string expectedResult = - "101000000000000110000000000000000010000000011000000000000000000000010000" - "00000000"; - - assert(result.compare(expectedResult) == 0); -} - -void testPayloadBase45Rep() { - printf("---Running Test--- %s\n", __FUNCTION__); - SetupPayload payload; - - payload.version = 5; - payload.vendorID = 12; - payload.productID = 1; - payload.requiresCustomFlow = 0; - payload.rendezvousInformation = 1; - payload.discriminator = 128; - payload.setUpPINCode = 2048; - - SetupPayloadGenerator generator(payload); - string result = generator.payloadBase45Representation(); - string expectedResult = "KABG8842Q000211"; - - assert(result.compare(expectedResult) == 0); -} - -void testBase45Encoding() { - printf("---Running Test--- %s\n", __FUNCTION__); - uint16_t input = 10; - string result = base45EncodedString(input, 3); - string expectedResult = "00A"; - assert(result.compare(expectedResult) == 0); -} - -void testBitsetLen() { - printf("---Running Test--- %s\n", __FUNCTION__); - assert(kTotalPayloadDataSizeInBits % 8 == 0); -} - -int main(int argc, char** argv) { - printf("---Running Test--- tests from %s\n", __FILE__); - testBitsetLen(); - testPayloadByteArrayRep(); - testPayloadBase45Rep(); - testBase45Encoding(); -} \ No newline at end of file diff --git a/src/qrcode/Makefile b/src/setup_payload/Makefile similarity index 75% rename from src/qrcode/Makefile rename to src/setup_payload/Makefile index 422526e61da0c7..49a27138ee5230 100644 --- a/src/qrcode/Makefile +++ b/src/setup_payload/Makefile @@ -1,9 +1,9 @@ TOP_DIR = ../.. Test_Dir = tests -.PHONY: all clean run_tests +.PHONY: all clean check -all: run_tests +all: libqr.a check include $(TOP_DIR)/.yams/cpp_rules.min @@ -17,12 +17,12 @@ Module_Test_Includes = $(Module_Includes) CPP_Files = \ SetupCodeUtils.cpp \ - SetupPayloadGenerator.cpp \ + QRCodeSetupPayloadGenerator.cpp \ libqr.a: $(CPP_Objects) ar rvs $@ $^ @echo "LINK => $@" clean: my_clean - @rm -f $(LIB_NAME) *.gcda *.gcno *.gcov + @rm -f libqr.a *.gcda *.gcno *.gcov diff --git a/src/qrcode/SetupPayloadGenerator.cpp b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp similarity index 73% rename from src/qrcode/SetupPayloadGenerator.cpp rename to src/setup_payload/QRCodeSetupPayloadGenerator.cpp index 42cfd7e6dde618..e374983fcd071d 100644 --- a/src/qrcode/SetupPayloadGenerator.cpp +++ b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp @@ -22,7 +22,7 @@ * */ -#include "SetupPayloadGenerator.h" +#include "QRCodeSetupPayloadGenerator.h" #include "SetupCodeUtils.h" #include @@ -31,14 +31,14 @@ using namespace chip; using namespace std; -void SetupPayloadGenerator::resetBitSet() +void QRCodeSetupPayloadGenerator::resetBitSet() { mPayloadBitsIndex = kTotalPayloadDataSizeInBits; mPayloadBits.reset(); } // Populates numberOfBits starting from LSB of input into mPayloadBits -void SetupPayloadGenerator::populateInteger(uint64_t input, size_t numberOfBits) +void QRCodeSetupPayloadGenerator::populateInteger(uint64_t input, size_t numberOfBits) { int numberOfBitsModified = 0; @@ -47,69 +47,68 @@ void SetupPayloadGenerator::populateInteger(uint64_t input, size_t numberOfBits) int endIndex = currentIndex + (numberOfBits - 1); - int itercount = 1; - while (currentIndex <= endIndex) { - itercount++; + while (currentIndex <= endIndex) + { input & 1 ? mPayloadBits.set(currentIndex) : mPayloadBits.reset(currentIndex); currentIndex++; input /= 2; } } -void SetupPayloadGenerator::populateVersion() +void QRCodeSetupPayloadGenerator::populateVersion() { populateInteger(mPayload.version, kVersionFieldLengthInBits); } -void SetupPayloadGenerator::populateVendorID() +void QRCodeSetupPayloadGenerator::populateVendorID() { populateInteger(mPayload.vendorID, kVendorIDFieldLengthInBits); } -void SetupPayloadGenerator::populateProductID() +void QRCodeSetupPayloadGenerator::populateProductID() { populateInteger(mPayload.productID, kProductIDFieldLengthInBits); } -void SetupPayloadGenerator::populateCustomFlowRequiredField() +void QRCodeSetupPayloadGenerator::populateCustomFlowRequiredField() { populateInteger(mPayload.requiresCustomFlow, kCustomFlowRequiredFieldLengthInBits); } -void SetupPayloadGenerator::populateRendezVousInfo() +void QRCodeSetupPayloadGenerator::populateRendezvousInfo() { populateInteger(mPayload.rendezvousInformation, kRendezvousInfoFieldLengthInBits); } -void SetupPayloadGenerator::populateDiscriminator() +void QRCodeSetupPayloadGenerator::populateDiscriminator() { populateInteger(mPayload.discriminator, kPayloadDiscriminatorFieldLengthInBits); } -void SetupPayloadGenerator::populateSetupPIN() +void QRCodeSetupPayloadGenerator::populateSetupPIN() { populateInteger(mPayload.setUpPINCode, kSetupPINCodeFieldLengthInBits); } -void SetupPayloadGenerator::populateReservedField() +void QRCodeSetupPayloadGenerator::populateReservedField() { populateInteger(0, kReservedFieldLengthInBits); } -void SetupPayloadGenerator::generateBitSet() +void QRCodeSetupPayloadGenerator::generateBitSet() { resetBitSet(); populateVersion(); populateVendorID(); populateProductID(); populateCustomFlowRequiredField(); - populateRendezVousInfo(); + populateRendezvousInfo(); populateDiscriminator(); populateSetupPIN(); populateReservedField(); } -string SetupPayloadGenerator::payloadBinaryRepresentation() +string QRCodeSetupPayloadGenerator::payloadBinaryRepresentation() { generateBitSet(); return mPayloadBits.to_string(); @@ -120,12 +119,12 @@ string SetupPayloadGenerator::payloadBinaryRepresentation() vector arrayFromBits(bitset bits) { vector resultVector; - size_t numberOfBits = bits.size(); + size_t numberOfBits = bits.size(); size_t numberOfBytes = numberOfBits / 8; - bool oddNumOfBytes = (numberOfBytes % 2) ? true : false; + bool oddNumOfBytes = (numberOfBytes % 2) ? true : false; // Traversing in reverse, hence startIndex > endIndex - int endIndex = 0; + int endIndex = 0; int startIndex = bits.size() - 1; /* @@ -133,14 +132,17 @@ vector arrayFromBits(bitset bits) If an odd number of bytes are to be encoded, the remaining single byte will be encoded to 2 characters of the Base-45 alphabet. */ - if (oddNumOfBytes) { - endIndex = 8; + if (oddNumOfBytes) + { + endIndex = 8; } - while (startIndex > endIndex) { + while (startIndex > endIndex) + { int currentIntegerIndex = startIndex; - uint16_t result = 0; - for (int i = currentIntegerIndex; i > currentIntegerIndex - 16; i--) { + uint16_t result = 0; + for (int i = currentIntegerIndex; i > currentIntegerIndex - 16; i--) + { result = result << 1; result = result | bits.test(i); } @@ -149,9 +151,11 @@ vector arrayFromBits(bitset bits) } // If we have odd number of bytes append the last byte. - if (oddNumOfBytes) { + if (oddNumOfBytes) + { uint16_t result = 0; - for (int i = 7; i >= 0 ; i--) { + for (int i = 7; i >= 0; i--) + { result = result << 1; result = result & bits.test(i); } @@ -160,12 +164,13 @@ vector arrayFromBits(bitset bits) return resultVector; } -string SetupPayloadGenerator::payloadBase45Representation() +string QRCodeSetupPayloadGenerator::payloadBase45Representation() { generateBitSet(); vector integerArray = arrayFromBits(mPayloadBits); string result; - for (int idx = 0; idx < integerArray.size(); idx++) { + for (int idx = 0; idx < integerArray.size(); idx++) + { result += base45EncodedString(integerArray[idx], 3); } return result; diff --git a/src/qrcode/SetupPayloadGenerator.h b/src/setup_payload/QRCodeSetupPayloadGenerator.h similarity index 94% rename from src/qrcode/SetupPayloadGenerator.h rename to src/setup_payload/QRCodeSetupPayloadGenerator.h index 99c88fd5eb37b8..d2261140b338a5 100644 --- a/src/qrcode/SetupPayloadGenerator.h +++ b/src/setup_payload/QRCodeSetupPayloadGenerator.h @@ -58,7 +58,7 @@ const int kTotalPayloadDataSizeInBits = ( kVersionFieldLengthInBits + \ namespace chip { -class SetupPayloadGenerator +class QRCodeSetupPayloadGenerator { private: bitset mPayloadBits; @@ -71,7 +71,7 @@ class SetupPayloadGenerator void populateVendorID(); void populateProductID(); void populateCustomFlowRequiredField(); - void populateRendezVousInfo(); + void populateRendezvousInfo(); void populateDiscriminator(); void populateSetupPIN(); void populateReservedField(); @@ -81,7 +81,7 @@ class SetupPayloadGenerator public: string payloadBinaryRepresentation(); string payloadBase45Representation(); - SetupPayloadGenerator(SetupPayload setupPayload) : mPayload(setupPayload) {}; + QRCodeSetupPayloadGenerator(SetupPayload setupPayload) : mPayload(setupPayload) {}; }; diff --git a/src/qrcode/SetupCodeUtils.cpp b/src/setup_payload/SetupCodeUtils.cpp similarity index 75% rename from src/qrcode/SetupCodeUtils.cpp rename to src/setup_payload/SetupCodeUtils.cpp index e791c74f4a5222..0ec8828eb50178 100644 --- a/src/qrcode/SetupCodeUtils.cpp +++ b/src/setup_payload/SetupCodeUtils.cpp @@ -29,26 +29,23 @@ using namespace std; namespace chip { -char base45CharacterSet[45] = -{ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', - '+', '-', '.', '/', ':' -}; +char base45CharacterSet[45] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', + 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':' }; string base45EncodedString(uint64_t input, size_t minLength) { string result; int radix = 45; - do { + do + { char base45char = base45CharacterSet[input % radix]; result += base45char; input = input / radix; } while (input != 0); - while (result.length() < minLength) { + while (result.length() < minLength) + { result.append("0"); } diff --git a/src/qrcode/SetupCodeUtils.h b/src/setup_payload/SetupCodeUtils.h similarity index 100% rename from src/qrcode/SetupCodeUtils.h rename to src/setup_payload/SetupCodeUtils.h diff --git a/src/qrcode/SetupPayload.h b/src/setup_payload/SetupPayload.h similarity index 100% rename from src/qrcode/SetupPayload.h rename to src/setup_payload/SetupPayload.h diff --git a/src/setup_payload/tests/tests.cpp b/src/setup_payload/tests/tests.cpp new file mode 100644 index 00000000000000..3ccd4eb41d4d87 --- /dev/null +++ b/src/setup_payload/tests/tests.cpp @@ -0,0 +1,92 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "SetupCodeUtils.cpp" +#include "SetupPayload.h" +#include "QRCodeSetupPayloadGenerator.cpp" + +using namespace chip; +using namespace std; + +void testPayloadByteArrayRep() +{ + printf("---Running Test--- %s\n", __FUNCTION__); + SetupPayload payload; + + payload.version = 5; + payload.vendorID = 12; + payload.productID = 1; + payload.requiresCustomFlow = 0; + payload.rendezvousInformation = 1; + payload.discriminator = 128; + payload.setUpPINCode = 2048; + + QRCodeSetupPayloadGenerator generator(payload); + string result = generator.payloadBinaryRepresentation(); + string expectedResult = "101000000000000110000000000000000010000000011000000000000000000000010000" + "00000000"; + + assert(result.compare(expectedResult) == 0); +} + +void testPayloadBase45Rep() +{ + printf("---Running Test--- %s\n", __FUNCTION__); + SetupPayload payload; + + payload.version = 5; + payload.vendorID = 12; + payload.productID = 1; + payload.requiresCustomFlow = 0; + payload.rendezvousInformation = 1; + payload.discriminator = 128; + payload.setUpPINCode = 2048; + + QRCodeSetupPayloadGenerator generator(payload); + string result = generator.payloadBase45Representation(); + string expectedResult = "KABG8842Q000211"; + + assert(result.compare(expectedResult) == 0); +} + +void testBase45Encoding() +{ + printf("---Running Test--- %s\n", __FUNCTION__); + uint16_t input = 10; + string result = base45EncodedString(input, 3); + string expectedResult = "00A"; + assert(result.compare(expectedResult) == 0); +} + +void testBitsetLen() +{ + printf("---Running Test--- %s\n", __FUNCTION__); + assert(kTotalPayloadDataSizeInBits % 8 == 0); +} + +int main(int argc, char ** argv) +{ + printf("---Running Test--- tests from %s\n", __FILE__); + testBitsetLen(); + testPayloadByteArrayRep(); + testPayloadBase45Rep(); + testBase45Encoding(); +} \ No newline at end of file From 6e4479cd310060acbf29c5b69b8efccee8942864 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Mon, 16 Mar 2020 13:31:54 -0700 Subject: [PATCH 4/7] Add basic input validation --- src/setup_payload/Makefile | 1 + .../QRCodeSetupPayloadGenerator.cpp | 26 ++++--- .../QRCodeSetupPayloadGenerator.h | 67 +++++++------------ src/setup_payload/SetupCodeUtils.cpp | 1 + src/setup_payload/SetupPayload.h | 22 ++++++ src/setup_payload/tests/tests.cpp | 1 + 6 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/setup_payload/Makefile b/src/setup_payload/Makefile index 49a27138ee5230..27e27697279dc0 100644 --- a/src/setup_payload/Makefile +++ b/src/setup_payload/Makefile @@ -17,6 +17,7 @@ Module_Test_Includes = $(Module_Includes) CPP_Files = \ SetupCodeUtils.cpp \ + SetupPayload.cpp \ QRCodeSetupPayloadGenerator.cpp \ libqr.a: $(CPP_Objects) diff --git a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp index e374983fcd071d..653d8908e5944e 100644 --- a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp +++ b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp @@ -40,8 +40,6 @@ void QRCodeSetupPayloadGenerator::resetBitSet() // Populates numberOfBits starting from LSB of input into mPayloadBits void QRCodeSetupPayloadGenerator::populateInteger(uint64_t input, size_t numberOfBits) { - int numberOfBitsModified = 0; - mPayloadBitsIndex -= numberOfBits; int currentIndex = mPayloadBitsIndex; @@ -110,8 +108,12 @@ void QRCodeSetupPayloadGenerator::generateBitSet() string QRCodeSetupPayloadGenerator::payloadBinaryRepresentation() { - generateBitSet(); - return mPayloadBits.to_string(); + if (mPayload.isValid()) + { + generateBitSet(); + return mPayloadBits.to_string(); + } + return string(); } // This function assumes bits.size() % 8 == 0 @@ -166,12 +168,16 @@ vector arrayFromBits(bitset bits) string QRCodeSetupPayloadGenerator::payloadBase45Representation() { - generateBitSet(); - vector integerArray = arrayFromBits(mPayloadBits); - string result; - for (int idx = 0; idx < integerArray.size(); idx++) + if (mPayload.isValid()) { - result += base45EncodedString(integerArray[idx], 3); + generateBitSet(); + vector integerArray = arrayFromBits(mPayloadBits); + string result; + for (int idx = 0; idx < integerArray.size(); idx++) + { + result += base45EncodedString(integerArray[idx], 3); + } + return result; } - return result; + return string(); } diff --git a/src/setup_payload/QRCodeSetupPayloadGenerator.h b/src/setup_payload/QRCodeSetupPayloadGenerator.h index d2261140b338a5..b2b75238bdbfee 100644 --- a/src/setup_payload/QRCodeSetupPayloadGenerator.h +++ b/src/setup_payload/QRCodeSetupPayloadGenerator.h @@ -33,58 +33,37 @@ #include using namespace std; -#ifndef _SETUP_PAYLOAD_GENERATOR_ -#define _SETUP_PAYLOAD_GENERATOR_ - -const int kVersionFieldLengthInBits = 3; -const int kVendorIDFieldLengthInBits = 16; -const int kProductIDFieldLengthInBits = 16; -const int kCustomFlowRequiredFieldLengthInBits = 1; -const int kRendezvousInfoFieldLengthInBits = 8; -const int kPayloadDiscriminatorFieldLengthInBits = 8; -const int kSetupPINCodeFieldLengthInBits = 27; -const int kReservedFieldLengthInBits = 1; - - -const int kTotalPayloadDataSizeInBits = ( kVersionFieldLengthInBits + \ - kVendorIDFieldLengthInBits + \ - kProductIDFieldLengthInBits + \ - kCustomFlowRequiredFieldLengthInBits + - kRendezvousInfoFieldLengthInBits + \ - kPayloadDiscriminatorFieldLengthInBits + \ - kSetupPINCodeFieldLengthInBits + \ - kReservedFieldLengthInBits - ); +#ifndef _QR_CODE_SETUP_PAYLOAD_GENERATOR_ +#define _QR_CODE_SETUP_PAYLOAD_GENERATOR_ namespace chip { class QRCodeSetupPayloadGenerator { - private: - bitset mPayloadBits; - SetupPayload mPayload; - // points to the current index within the bitset - int mPayloadBitsIndex; - - void populateInteger(uint64_t input, size_t numberOfBits); - void populateVersion(); - void populateVendorID(); - void populateProductID(); - void populateCustomFlowRequiredField(); - void populateRendezvousInfo(); - void populateDiscriminator(); - void populateSetupPIN(); - void populateReservedField(); - void resetBitSet(); - void generateBitSet(); +private: + bitset mPayloadBits; + SetupPayload mPayload; + // points to the current index within the bitset + int mPayloadBitsIndex; - public: - string payloadBinaryRepresentation(); - string payloadBase45Representation(); - QRCodeSetupPayloadGenerator(SetupPayload setupPayload) : mPayload(setupPayload) {}; + void populateInteger(uint64_t input, size_t numberOfBits); + void populateVersion(); + void populateVendorID(); + void populateProductID(); + void populateCustomFlowRequiredField(); + void populateRendezvousInfo(); + void populateDiscriminator(); + void populateSetupPIN(); + void populateReservedField(); + void resetBitSet(); + void generateBitSet(); +public: + string payloadBinaryRepresentation(); + string payloadBase45Representation(); + QRCodeSetupPayloadGenerator(SetupPayload setupPayload) : mPayload(setupPayload){}; }; }; // namespace chip -#endif /* _SETUP_PAYLOAD_GENERATOR_ */ \ No newline at end of file +#endif /* _QR_CODE_SETUP_PAYLOAD_GENERATOR_ */ \ No newline at end of file diff --git a/src/setup_payload/SetupCodeUtils.cpp b/src/setup_payload/SetupCodeUtils.cpp index 0ec8828eb50178..c688e65c2de4c9 100644 --- a/src/setup_payload/SetupCodeUtils.cpp +++ b/src/setup_payload/SetupCodeUtils.cpp @@ -24,6 +24,7 @@ #include "SetupCodeUtils.h" #include +#include using namespace std; diff --git a/src/setup_payload/SetupPayload.h b/src/setup_payload/SetupPayload.h index b49ca5ec800bb9..a5dca52a9ac95b 100644 --- a/src/setup_payload/SetupPayload.h +++ b/src/setup_payload/SetupPayload.h @@ -29,6 +29,25 @@ namespace chip { +const int kVersionFieldLengthInBits = 3; +const int kVendorIDFieldLengthInBits = 16; +const int kProductIDFieldLengthInBits = 16; +const int kCustomFlowRequiredFieldLengthInBits = 1; +const int kRendezvousInfoFieldLengthInBits = 8; +const int kPayloadDiscriminatorFieldLengthInBits = 8; +const int kSetupPINCodeFieldLengthInBits = 27; +const int kReservedFieldLengthInBits = 1; + +const int kTotalPayloadDataSizeInBits = ( kVersionFieldLengthInBits + \ + kVendorIDFieldLengthInBits + \ + kProductIDFieldLengthInBits + \ + kCustomFlowRequiredFieldLengthInBits + \ + kRendezvousInfoFieldLengthInBits + \ + kPayloadDiscriminatorFieldLengthInBits + \ + kSetupPINCodeFieldLengthInBits + \ + kReservedFieldLengthInBits + ); + class SetupPayload { public: @@ -39,6 +58,9 @@ class SetupPayload uint16_t rendezvousInformation; uint16_t discriminator; uint32_t setUpPINCode; + + // Test that the Setup Payload is within expected value ranges + bool isValid(); }; }; // namespace chip diff --git a/src/setup_payload/tests/tests.cpp b/src/setup_payload/tests/tests.cpp index 3ccd4eb41d4d87..579d7ad1684e7c 100644 --- a/src/setup_payload/tests/tests.cpp +++ b/src/setup_payload/tests/tests.cpp @@ -19,6 +19,7 @@ #include +#include "SetupPayload.cpp" #include "SetupCodeUtils.cpp" #include "SetupPayload.h" #include "QRCodeSetupPayloadGenerator.cpp" From 331843a7928d2fa47e21791f058c00af95d11c1c Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Mon, 16 Mar 2020 15:14:31 -0700 Subject: [PATCH 5/7] Add test for Payload inputs --- .../QRCodeSetupPayloadGenerator.cpp | 4 ++ src/setup_payload/SetupPayload.h | 2 +- src/setup_payload/tests/tests.cpp | 37 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp index 653d8908e5944e..f5032309276c94 100644 --- a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp +++ b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp @@ -40,6 +40,10 @@ void QRCodeSetupPayloadGenerator::resetBitSet() // Populates numberOfBits starting from LSB of input into mPayloadBits void QRCodeSetupPayloadGenerator::populateInteger(uint64_t input, size_t numberOfBits) { + if (mPayloadBitsIndex < numberOfBits || input >= 1 << numberOfBits) + { + abort(); + } mPayloadBitsIndex -= numberOfBits; int currentIndex = mPayloadBitsIndex; diff --git a/src/setup_payload/SetupPayload.h b/src/setup_payload/SetupPayload.h index a5dca52a9ac95b..73d5c699f45278 100644 --- a/src/setup_payload/SetupPayload.h +++ b/src/setup_payload/SetupPayload.h @@ -28,7 +28,7 @@ #include namespace chip { - +// TODO this shuould point to the spec const int kVersionFieldLengthInBits = 3; const int kVendorIDFieldLengthInBits = 16; const int kProductIDFieldLengthInBits = 16; diff --git a/src/setup_payload/tests/tests.cpp b/src/setup_payload/tests/tests.cpp index 579d7ad1684e7c..4b0afff03de050 100644 --- a/src/setup_payload/tests/tests.cpp +++ b/src/setup_payload/tests/tests.cpp @@ -83,6 +83,42 @@ void testBitsetLen() assert(kTotalPayloadDataSizeInBits % 8 == 0); } +void testSetupPayloadVerify() +{ + printf("---Running Test--- %s\n", __FUNCTION__); + SetupPayload payload; + + payload.version = 5; + payload.vendorID = 12; + payload.productID = 1; + payload.requiresCustomFlow = 0; + payload.rendezvousInformation = 1; + payload.discriminator = 128; + payload.setUpPINCode = 2048; + + assert(payload.isValid()); + + // test invalid version + SetupPayload test_payload = payload; + test_payload.version = 2 << kVersionFieldLengthInBits; + assert(!test_payload.isValid()); + + // test invalid rendezvousInformation + test_payload = payload; + test_payload.rendezvousInformation = 3; + assert(!test_payload.isValid()); + + // test invalid discriminator + test_payload = payload; + test_payload.discriminator = 2 << kPayloadDiscriminatorFieldLengthInBits; + assert(!test_payload.isValid()); + + // test invalid stetup PIN + test_payload = payload; + test_payload.setUpPINCode = 2 << kSetupPINCodeFieldLengthInBits; + assert(!test_payload.isValid()); +} + int main(int argc, char ** argv) { printf("---Running Test--- tests from %s\n", __FILE__); @@ -90,4 +126,5 @@ int main(int argc, char ** argv) testPayloadByteArrayRep(); testPayloadBase45Rep(); testBase45Encoding(); + testSetupPayloadVerify(); } \ No newline at end of file From 0a81a84779188c559c68244fae625d359d2b1245 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Mon, 16 Mar 2020 15:48:55 -0700 Subject: [PATCH 6/7] Fix Docker build --- src/setup_payload/QRCodeSetupPayloadGenerator.cpp | 2 ++ src/setup_payload/SetupCodeUtils.h | 1 + src/setup_payload/tests/tests.cpp | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp index f5032309276c94..6db31f5bb280ff 100644 --- a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp +++ b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp @@ -28,6 +28,8 @@ #include #include +#include + using namespace chip; using namespace std; diff --git a/src/setup_payload/SetupCodeUtils.h b/src/setup_payload/SetupCodeUtils.h index ba4ad9b2301abb..caa339316d652f 100644 --- a/src/setup_payload/SetupCodeUtils.h +++ b/src/setup_payload/SetupCodeUtils.h @@ -24,6 +24,7 @@ #define _SETUP_CODE_UTILS_H_ #include +#include using namespace std; diff --git a/src/setup_payload/tests/tests.cpp b/src/setup_payload/tests/tests.cpp index 4b0afff03de050..34ad882d733118 100644 --- a/src/setup_payload/tests/tests.cpp +++ b/src/setup_payload/tests/tests.cpp @@ -16,6 +16,8 @@ */ #include +#include +#include #include From 76693647d90e6cff1e15793dd35e26926a7463a4 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Mon, 16 Mar 2020 15:51:58 -0700 Subject: [PATCH 7/7] Add missing source file --- src/setup_payload/SetupPayload.cpp | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/setup_payload/SetupPayload.cpp diff --git a/src/setup_payload/SetupPayload.cpp b/src/setup_payload/SetupPayload.cpp new file mode 100644 index 00000000000000..a174089a24d0fc --- /dev/null +++ b/src/setup_payload/SetupPayload.cpp @@ -0,0 +1,60 @@ +/* + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * The implementation of the Setup Payload. Currently only needed to + * verify the validity of a Setup Payload + */ + +#include "SetupPayload.h" + +namespace chip { + +// Check the Setup Payload for validity +// +// `vendor_id` and `product_id` are allowed all of uint16_t +// `requiresCustomFlow` is not checked since it is a bool +bool SetupPayload::isValid() +{ + if (version >= 1 << kVersionFieldLengthInBits) + { + return false; + } + if (rendezvousInformation >= 1 << kRendezvousInfoFieldLengthInBits) + { + return false; + } + if (discriminator >= 1 << kPayloadDiscriminatorFieldLengthInBits) + { + return false; + } + if (setUpPINCode >= 1 << kSetupPINCodeFieldLengthInBits) + { + return false; + } + // make sure the rendezvousInformation only uses allowed values + // i.e it must be > 0 and set to 1 or a power of 2. + uint16_t rezInfo = rendezvousInformation; + if (rezInfo == 0 || (rezInfo != 1 && (rezInfo & (rezInfo - 1)) != 0)) + { + return false; + } + return true; +} + +} // namespace chip \ No newline at end of file