Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2020 Project CHIP Authors 4 : * 5 : * Licensed under the Apache License, Version 2.0 (the "License"); 6 : * you may not use this file except in compliance with the License. 7 : * You may obtain a copy of the License at 8 : * 9 : * http://www.apache.org/licenses/LICENSE-2.0 10 : * 11 : * Unless required by applicable law or agreed to in writing, software 12 : * distributed under the License is distributed on an "AS IS" BASIS, 13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 : * See the License for the specific language governing permissions and 15 : * limitations under the License. 16 : */ 17 : 18 : /** 19 : * @file 20 : * This file describes a QRCode Setup Payload class to hold 21 : * data enumerated from a byte stream 22 : */ 23 : 24 : #pragma once 25 : 26 : #include <cstdint> 27 : #include <map> 28 : #include <string> 29 : #include <vector> 30 : 31 : #include <lib/core/CHIPError.h> 32 : #include <lib/core/Optional.h> 33 : #include <lib/support/BitFlags.h> 34 : #include <lib/support/SetupDiscriminator.h> 35 : 36 : namespace chip { 37 : 38 : // See section 5.1.2. QR Code in the Matter specification 39 : const int kVersionFieldLengthInBits = 3; 40 : const int kVendorIDFieldLengthInBits = 16; 41 : const int kProductIDFieldLengthInBits = 16; 42 : const int kCommissioningFlowFieldLengthInBits = 2; 43 : const int kRendezvousInfoFieldLengthInBits = 8; 44 : const int kPayloadDiscriminatorFieldLengthInBits = SetupDiscriminator::kLongBits; 45 : const int kSetupPINCodeFieldLengthInBits = 27; 46 : const int kPaddingFieldLengthInBits = 4; 47 : const int kRawVendorTagLengthInBits = 7; 48 : 49 : // See section 5.1.3. Manual Pairing Code in the Matter specification 50 : const int kManualSetupDiscriminatorFieldLengthInBits = SetupDiscriminator::kShortBits; 51 : const int kManualSetupChunk1DiscriminatorMsbitsPos = 0; 52 : const int kManualSetupChunk1DiscriminatorMsbitsLength = 2; 53 : const int kManualSetupChunk1VidPidPresentBitPos = 54 : (kManualSetupChunk1DiscriminatorMsbitsPos + kManualSetupChunk1DiscriminatorMsbitsLength); 55 : const int kManualSetupChunk2PINCodeLsbitsPos = 0; 56 : const int kManualSetupChunk2PINCodeLsbitsLength = 14; 57 : const int kManualSetupChunk2DiscriminatorLsbitsPos = (kManualSetupChunk2PINCodeLsbitsPos + kManualSetupChunk2PINCodeLsbitsLength); 58 : const int kManualSetupChunk2DiscriminatorLsbitsLength = 2; 59 : const int kManualSetupChunk3PINCodeMsbitsPos = 0; 60 : const int kManualSetupChunk3PINCodeMsbitsLength = 13; 61 : 62 : const int kManualSetupShortCodeCharLength = 10; 63 : const int kManualSetupLongCodeCharLength = 20; 64 : const int kManualSetupCodeChunk1CharLength = 1; 65 : const int kManualSetupCodeChunk2CharLength = 5; 66 : const int kManualSetupCodeChunk3CharLength = 4; 67 : const int kManualSetupVendorIdCharLength = 5; 68 : const int kManualSetupProductIdCharLength = 5; 69 : 70 : // Spec 5.1.4.2 CHIP-Common Reserved Tags 71 : inline constexpr uint8_t kSerialNumberTag = 0x00; 72 : inline constexpr uint8_t kPBKDFIterationsTag = 0x01; 73 : inline constexpr uint8_t kBPKFSaltTag = 0x02; 74 : inline constexpr uint8_t kNumberOFDevicesTag = 0x03; 75 : inline constexpr uint8_t kCommissioningTimeoutTag = 0x04; 76 : 77 : inline constexpr uint32_t kSetupPINCodeMaximumValue = 99999998; 78 : inline constexpr uint32_t kSetupPINCodeUndefinedValue = 0; 79 : 80 : // clang-format off 81 : const int kTotalPayloadDataSizeInBits = 82 : kVersionFieldLengthInBits + 83 : kVendorIDFieldLengthInBits + 84 : kProductIDFieldLengthInBits + 85 : kCommissioningFlowFieldLengthInBits + 86 : kRendezvousInfoFieldLengthInBits + 87 : kPayloadDiscriminatorFieldLengthInBits + 88 : kSetupPINCodeFieldLengthInBits + 89 : kPaddingFieldLengthInBits; 90 : // clang-format on 91 : 92 : const int kTotalPayloadDataSizeInBytes = kTotalPayloadDataSizeInBits / 8; 93 : 94 : const char * const kQRCodePrefix = "MT:"; 95 : 96 : /// The rendezvous type this device supports. 97 : enum class RendezvousInformationFlag : uint8_t 98 : { 99 : kNone = 0, ///< Device does not support any method for rendezvous 100 : kSoftAP = 1 << 0, ///< Device supports Wi-Fi softAP 101 : kBLE = 1 << 1, ///< Device supports BLE 102 : kOnNetwork = 1 << 2, ///< Device supports Setup on network 103 : }; 104 : using RendezvousInformationFlags = chip::BitFlags<RendezvousInformationFlag, uint8_t>; 105 : 106 : enum class CommissioningFlow : uint8_t 107 : { 108 : kStandard = 0, ///< Device automatically enters pairing mode upon power-up 109 : kUserActionRequired, ///< Device requires a user interaction to enter pairing mode 110 : kCustom, ///< Commissioning steps should be retrieved from the distributed compliance ledger 111 : }; 112 : 113 : /** 114 : * A parent struct to hold onboarding payload contents without optional info, 115 : * for compatibility with devices that don't support std::string or STL. 116 : */ 117 : struct PayloadContents 118 : { 119 : uint8_t version = 0; 120 : uint16_t vendorID = 0; 121 : uint16_t productID = 0; 122 : CommissioningFlow commissioningFlow = CommissioningFlow::kStandard; 123 : // rendezvousInformation is Optional, because a payload parsed from a manual 124 : // numeric code would not have any rendezvousInformation available. A 125 : // payload parsed from a QR code would always have a value for 126 : // rendezvousInformation. 127 : Optional<RendezvousInformationFlags> rendezvousInformation; 128 : SetupDiscriminator discriminator; 129 : uint32_t setUpPINCode = 0; 130 : 131 : bool isValidQRCodePayload() const; 132 : bool isValidManualCode() const; 133 : bool operator==(PayloadContents & input) const; 134 : 135 : static bool IsValidSetupPIN(uint32_t setupPIN); 136 : 137 : private: 138 : bool CheckPayloadCommonConstraints() const; 139 : }; 140 : 141 : enum optionalQRCodeInfoType 142 : { 143 : optionalQRCodeInfoTypeUnknown, 144 : optionalQRCodeInfoTypeString, 145 : optionalQRCodeInfoTypeInt32, 146 : optionalQRCodeInfoTypeInt64, 147 : optionalQRCodeInfoTypeUInt32, 148 : optionalQRCodeInfoTypeUInt64 149 : }; 150 : 151 : /** 152 : * A structure to hold optional QR Code info 153 : */ 154 : struct OptionalQRCodeInfo 155 : { 156 72 : OptionalQRCodeInfo() { int32 = 0; } 157 : 158 : /*@{*/ 159 : uint8_t tag; /**< the tag number of the optional info */ 160 : enum optionalQRCodeInfoType type; /**< the type (String or Int) of the optional info */ 161 : std::string data; /**< the string value if type is optionalQRCodeInfoTypeString, otherwise should not be set */ 162 : int32_t int32; /**< the integer value if type is optionalQRCodeInfoTypeInt, otherwise should not be set */ 163 : /*@}*/ 164 : }; 165 : 166 : struct OptionalQRCodeInfoExtension : OptionalQRCodeInfo 167 : { 168 29 : OptionalQRCodeInfoExtension() 169 29 : { 170 29 : int32 = 0; 171 29 : int64 = 0; 172 29 : uint32 = 0; 173 29 : uint64 = 0; 174 29 : } 175 : 176 : int64_t int64; 177 : uint64_t uint32; 178 : uint64_t uint64; 179 : }; 180 : 181 : class SetupPayload : public PayloadContents 182 : { 183 : 184 : friend class QRCodeSetupPayloadGenerator; 185 : friend class QRCodeSetupPayloadParser; 186 : 187 : public: 188 : /** @brief A function to add an optional vendor data 189 : * @param tag tag number in the [0x80-0xFF] range 190 : * @param data String representation of data to add 191 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 192 : **/ 193 : CHIP_ERROR addOptionalVendorData(uint8_t tag, std::string data); 194 : 195 : /** @brief A function to add an optional vendor data 196 : * @param tag 7 bit [0-127] tag number 197 : * @param data Integer representation of data to add 198 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 199 : **/ 200 : CHIP_ERROR addOptionalVendorData(uint8_t tag, int32_t data); 201 : 202 : /** @brief A function to remove an optional vendor data 203 : * @param tag 7 bit [0-127] tag number 204 : * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise 205 : **/ 206 : CHIP_ERROR removeOptionalVendorData(uint8_t tag); 207 : /** 208 : * @brief A function to retrieve the vector of OptionalQRCodeInfo infos 209 : * @return Returns a vector of optionalQRCodeInfos 210 : **/ 211 : std::vector<OptionalQRCodeInfo> getAllOptionalVendorData() const; 212 : 213 : /** @brief A function to add a string serial number 214 : * @param serialNumber string serial number 215 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 216 : **/ 217 : CHIP_ERROR addSerialNumber(std::string serialNumber); 218 : 219 : /** @brief A function to add a uint32_t serial number 220 : * @param serialNumber uint32_t serial number 221 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 222 : **/ 223 : CHIP_ERROR addSerialNumber(uint32_t serialNumber); 224 : 225 : /** @brief A function to retrieve serial number as a string 226 : * @param outSerialNumber retrieved string serial number 227 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 228 : **/ 229 : CHIP_ERROR getSerialNumber(std::string & outSerialNumber) const; 230 : 231 : /** @brief A function to remove the serial number from the payload 232 : * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise 233 : **/ 234 : CHIP_ERROR removeSerialNumber(); 235 : 236 : bool operator==(SetupPayload & input); 237 : 238 : private: 239 : std::map<uint8_t, OptionalQRCodeInfo> optionalVendorData; 240 : std::map<uint8_t, OptionalQRCodeInfoExtension> optionalExtensionData; 241 : 242 : /** @brief Checks if the tag is CHIP Common type 243 : * @param tag Tag to be checked 244 : * @return Returns True if the tag is of Common type 245 : **/ 246 : static bool IsCommonTag(uint8_t tag); 247 : 248 : /** @brief Checks if the tag is vendor-specific 249 : * @param tag Tag to be checked 250 : * @return Returns True if the tag is Vendor-specific 251 : **/ 252 : static bool IsVendorTag(uint8_t tag); 253 : 254 : /** @brief A function to add an optional QR Code info vendor object 255 : * @param info Optional QR code info object to add 256 : * @return Returns a CHIP_ERROR_INVALID_ARGUMENT on error, CHIP_NO_ERROR otherwise 257 : **/ 258 : CHIP_ERROR addOptionalVendorData(const OptionalQRCodeInfo & info); 259 : 260 : /** @brief A function to add an optional QR Code info CHIP object 261 : * @param info Optional QR code info object to add 262 : * @return Returns a CHIP_ERROR_INVALID_ARGUMENT on error, CHIP_NO_ERROR otherwise 263 : **/ 264 : CHIP_ERROR addOptionalExtensionData(const OptionalQRCodeInfoExtension & info); 265 : 266 : /** 267 : * @brief A function to retrieve the vector of CHIPQRCodeInfo infos 268 : * @return Returns a vector of CHIPQRCodeInfos 269 : **/ 270 : std::vector<OptionalQRCodeInfoExtension> getAllOptionalExtensionData(); 271 : 272 : /** @brief A function to retrieve an optional QR Code info vendor object 273 : * @param tag 7 bit [0-127] tag number 274 : * @param info retrieved OptionalQRCodeInfo object 275 : * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise 276 : **/ 277 : CHIP_ERROR getOptionalVendorData(uint8_t tag, OptionalQRCodeInfo & info); 278 : 279 : /** @brief A function to retrieve an optional QR Code info extended object 280 : * @param tag 8 bit [128-255] tag number 281 : * @param info retrieved OptionalQRCodeInfoExtension object 282 : * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise 283 : **/ 284 : CHIP_ERROR getOptionalExtensionData(uint8_t tag, OptionalQRCodeInfoExtension & info) const; 285 : 286 : /** @brief A function to retrieve the associated expected numeric value for a tag 287 : * @param tag 8 bit [0-255] tag number 288 : * @return Returns an optionalQRCodeInfoType value 289 : **/ 290 : optionalQRCodeInfoType getNumericTypeFor(uint8_t tag); 291 : }; 292 : 293 : } // namespace chip