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

Base45 to a Set up payload #164

Merged
merged 2 commits into from
Mar 31, 2020
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
11 changes: 8 additions & 3 deletions src/setup_payload/Base45.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@

#include "Base45.h"

#include <iostream>

using namespace std;

namespace chip {

static const int kBase45ChunkLen = 3;
static const int kBytesChunkLen = 2;

string base45Encode(const uint8_t * buf, size_t buf_len)
{
Expand All @@ -46,7 +49,8 @@ string base45Encode(const uint8_t * buf, size_t buf_len)

// eat little-endian uint16_ts from the byte array
// encode as 3 base45 characters
while (buf_len >= 2)

while (buf_len >= kBytesChunkLen)
{
int next = buf[0] + buf[1] * 256;

Expand All @@ -55,8 +59,8 @@ string base45Encode(const uint8_t * buf, size_t buf_len)
result += codes[next % radix];
next /= radix;
}
buf += 2;
buf_len -= 2;
buf += kBytesChunkLen;
buf_len -= kBytesChunkLen;
}
// handle leftover byte, if any
if (buf_len != 0)
Expand Down Expand Up @@ -156,6 +160,7 @@ CHIP_ERROR base45Decode(string base45, vector<uint8_t> & result)
// base45 characters
if (base45.length() % kBase45ChunkLen == 1)
{
fprintf(stderr, "\nFailed decoding base45. Input was too short. %lu", base45.length());
return CHIP_ERROR_INVALID_MESSAGE_LENGTH;
}
result.clear();
Expand Down
13 changes: 11 additions & 2 deletions src/setup_payload/QRCodeSetupPayloadGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static void populateBits(uint8_t * bits, int & offset, uint64_t input, size_t nu
// do nothing in the case where we've overflowed. should never happen
if (offset + numberOfBits > kTotalPayloadDataSizeInBits || input >= 1u << numberOfBits)
{
fprintf(stderr, "Overflow while trying to generate a QR Code. Bailing.");
return;
}

Expand Down Expand Up @@ -86,7 +87,11 @@ string QRCodeSetupPayloadGenerator::payloadBinaryRepresentation()
}
return binary;
}
return string();
else
{
fprintf(stderr, "\nFailed encoding invalid payload\n");
return string();
}
}

string QRCodeSetupPayloadGenerator::payloadBase45Representation()
Expand All @@ -99,5 +104,9 @@ string QRCodeSetupPayloadGenerator::payloadBase45Representation()

return base45Encode(bits, sizeof(bits) / sizeof(bits[0]));
}
return string();
else
{
fprintf(stderr, "\nFailed encoding invalid payload\n");
return string();
}
}
1 change: 0 additions & 1 deletion src/setup_payload/QRCodeSetupPayloadGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@

#include "SetupPayload.h"

#include <bitset>
#include <string>
using namespace std;

Expand Down
123 changes: 123 additions & 0 deletions src/setup_payload/QRCodeSetupPayloadParser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
*
* <COPYRIGHT>
*
* 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 parser based on the
* CHIP specification.
*/

#include "QRCodeSetupPayloadParser.h"
#include "Base45.h"

#include <core/CHIPError.h>
#include <iostream>
#include <vector>

using namespace chip;
using namespace std;

// Populate numberOfBits into dest from buf starting at startIndex
static CHIP_ERROR readBits(vector<uint8_t> buf, int & index, uint64_t & dest, size_t numberOfBitsToRead)
{
dest = 0;
if (index + numberOfBitsToRead > buf.size() * 8 || numberOfBitsToRead > sizeof(uint64_t) * 8)
{
fprintf(stderr, "Error parsing QR code. startIndex %d numberOfBitsToLoad %zu buf_len %zu ", index, numberOfBitsToRead,
buf.size());
return CHIP_ERROR_INVALID_ARGUMENT;
}

int currentIndex = index;
for (size_t bitsRead = 0; bitsRead < numberOfBitsToRead; bitsRead++)
{
if (buf[currentIndex / 8] & (1 << (currentIndex % 8)))
{
dest |= (1 << bitsRead);
}
currentIndex++;
}
index += numberOfBitsToRead;
return CHIP_NO_ERROR;
}

CHIP_ERROR QRCodeSetupPayloadParser::populatePayload(SetupPayload & outPayload)
{
vector<uint8_t> buf = vector<uint8_t>();

CHIP_ERROR result = base45Decode(mBase45Representation, buf);

if (CHIP_NO_ERROR != result)
{
fprintf(stderr, "Decoding of base45 string failed");
return result;
}

int indexToReadFrom = 0;
uint64_t dest;

result = readBits(buf, indexToReadFrom, dest, kVersionFieldLengthInBits);
if (result != CHIP_NO_ERROR)
{
return result;
}
outPayload.version = dest;

result = readBits(buf, indexToReadFrom, dest, kVendorIDFieldLengthInBits);
if (result != CHIP_NO_ERROR)
{
return result;
}
outPayload.vendorID = dest;

result = readBits(buf, indexToReadFrom, dest, kProductIDFieldLengthInBits);
if (result != CHIP_NO_ERROR)
{
return result;
}
outPayload.productID = dest;

result = readBits(buf, indexToReadFrom, dest, kCustomFlowRequiredFieldLengthInBits);
if (result != CHIP_NO_ERROR)
{
return result;
}
outPayload.requiresCustomFlow = dest;

result = readBits(buf, indexToReadFrom, dest, kRendezvousInfoFieldLengthInBits);
if (result != CHIP_NO_ERROR)
{
return result;
}
outPayload.rendezvousInformation = dest;

result = readBits(buf, indexToReadFrom, dest, kPayloadDiscriminatorFieldLengthInBits);
if (result != CHIP_NO_ERROR)
{
return result;
}
outPayload.discriminator = dest;

result = readBits(buf, indexToReadFrom, dest, kSetupPINCodeFieldLengthInBits);
if (result != CHIP_NO_ERROR)
{
return result;
}
outPayload.setUpPINCode = dest;

return result;
}
46 changes: 46 additions & 0 deletions src/setup_payload/QRCodeSetupPayloadParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
*
* <COPYRIGHT>
*
* 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 parser based on the
* CHIP specification.
*/

#include "SetupPayload.h"

#include <core/CHIPError.h>
#include <string>
using namespace std;

namespace chip {

/**
* @class QRCodeSetupPayloadParser
* A class that can be used to convert a base45 encoded payload to a SetupPayload object
* */
class QRCodeSetupPayloadParser
{
private:
string mBase45Representation;

public:
QRCodeSetupPayloadParser(string base45Representation) : mBase45Representation(base45Representation){};
CHIP_ERROR populatePayload(SetupPayload & outPayload);
};

}; // namespace chip
14 changes: 10 additions & 4 deletions src/setup_payload/SetupPayload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,20 @@ bool SetupPayload::isValid()
{
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.
bhaskar-apple marked this conversation as resolved.
Show resolved Hide resolved
uint16_t rezInfo = rendezvousInformation;
if (rezInfo == 0 || (rezInfo != 1 && (rezInfo & (rezInfo - 1)) != 0))

if (version == 0 && rendezvousInformation == 0 && discriminator == 0 && setUpPINCode == 0)
{
return false;
}

return true;
}

bool SetupPayload::operator==(const SetupPayload & input)
{
return this->version == input.version && this->vendorID == input.vendorID && this->productID == input.productID &&
this->requiresCustomFlow == input.requiresCustomFlow && this->rendezvousInformation == input.rendezvousInformation &&
this->discriminator == input.discriminator && this->setUpPINCode == input.setUpPINCode;
}

} // namespace chip
7 changes: 7 additions & 0 deletions src/setup_payload/SetupPayload.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#define _SETUP_PAYLOAD_H_

#include <stdint.h>
#include <string>

using namespace std;

namespace chip {
// TODO this shuould point to the spec
Expand Down Expand Up @@ -55,7 +58,11 @@ class SetupPayload
uint32_t setUpPINCode;

// Test that the Setup Payload is within expected value ranges
SetupPayload() :
version(0), vendorID(0), productID(0), requiresCustomFlow(0), rendezvousInformation(0), discriminator(0), setUpPINCode(0){};

bool isValid();
bool operator==(const SetupPayload & input);
};

}; // namespace chip
Expand Down
2 changes: 1 addition & 1 deletion src/setup_payload/tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ TESTS_ENVIRONMENT = \
# Source, compiler, and linker options for test programs.

TestQrCode_LDADD = $(COMMON_LDADD)
TestQrCode_SOURCES = tests.cpp
TestQrCode_SOURCES = tests_qrcode.cpp

if CHIP_BUILD_COVERAGE
CLEANFILES = $(wildcard *.gcda *.gcno)
Expand Down
Loading