Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2021 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 provides a utility to generate Additional Data payload and its members 21 : * (e.g. rotating device id) 22 : * 23 : */ 24 : 25 : #include "AdditionalDataPayloadGenerator.h" 26 : #include "AdditionalDataPayload.h" 27 : 28 : #include <crypto/CHIPCryptoPAL.h> 29 : #include <lib/core/CHIPCore.h> 30 : #include <lib/core/CHIPEncoding.h> 31 : #include <lib/core/CHIPSafeCasts.h> 32 : #include <lib/core/TLV.h> 33 : #include <lib/support/BufferWriter.h> 34 : #include <lib/support/BytesToHex.h> 35 : #include <lib/support/CHIPMem.h> 36 : #include <stdlib.h> 37 : 38 : using namespace chip; 39 : using namespace chip::System; 40 : using namespace chip::TLV; 41 : using namespace chip::Crypto; 42 : using namespace chip::SetupPayloadData; 43 : using namespace chip::Encoding::LittleEndian; 44 : 45 : using chip::Encoding::BytesToUppercaseHexString; 46 : 47 : CHIP_ERROR 48 1 : AdditionalDataPayloadGenerator::generateAdditionalDataPayload(AdditionalDataPayloadGeneratorParams & params, 49 : PacketBufferHandle & bufferHandle, 50 : BitFlags<AdditionalDataFields> additionalDataFields) 51 : { 52 1 : System::PacketBufferTLVWriter writer; 53 1 : TLVWriter innerWriter; 54 : 55 : // Initialize TLVWriter 56 1 : auto tempBuffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize); 57 1 : VerifyOrReturnError(!tempBuffer.IsNull(), CHIP_ERROR_NO_MEMORY); 58 1 : writer.Init(std::move(tempBuffer)); 59 : 60 1 : ReturnErrorOnFailure(writer.OpenContainer(AnonymousTag(), kTLVType_Structure, innerWriter)); 61 : 62 : #if CHIP_ENABLE_ROTATING_DEVICE_ID 63 : if (additionalDataFields.Has(AdditionalDataFields::RotatingDeviceId)) 64 : { 65 : uint8_t rotatingDeviceIdInternalBuffer[RotatingDeviceId::kMaxLength]; 66 : MutableByteSpan rotatingDeviceIdBuffer(rotatingDeviceIdInternalBuffer); 67 : 68 : // Generating Device Rotating Id 69 : ReturnErrorOnFailure(generateRotatingDeviceIdAsBinary(params, rotatingDeviceIdBuffer)); 70 : // Adding the rotating device id to the TLV data 71 : ReturnErrorOnFailure(innerWriter.Put(ContextTag(kRotatingDeviceIdTag), rotatingDeviceIdBuffer)); 72 : } 73 : #endif 74 : 75 1 : ReturnErrorOnFailure(writer.CloseContainer(innerWriter)); 76 : 77 1 : return writer.Finalize(&bufferHandle); 78 1 : } 79 : 80 : #if CHIP_ENABLE_ROTATING_DEVICE_ID 81 : CHIP_ERROR AdditionalDataPayloadGenerator::generateRotatingDeviceIdAsBinary(AdditionalDataPayloadGeneratorParams & params, 82 : MutableByteSpan & rotatingDeviceIdBuffer) 83 : { 84 : uint8_t hashOutputBuffer[kSHA256_Hash_Length]; 85 : BufferWriter outputBufferWriter(rotatingDeviceIdBuffer); 86 : uint8_t lifetimeCounterBuffer[2]; 87 : 88 : if (params.rotatingDeviceIdUniqueId.data() == nullptr) 89 : { 90 : return CHIP_ERROR_INVALID_ARGUMENT; 91 : } 92 : 93 : Put16(lifetimeCounterBuffer, params.rotatingDeviceIdLifetimeCounter); 94 : 95 : // Computing the Rotating Device Id 96 : // RDI = Lifetime_Counter + SuffixBytes(SHA256(Unique_Id + Lifetime_Counter), 16) 97 : 98 : Hash_SHA256_stream hash; 99 : MutableByteSpan hashOutputSpan(hashOutputBuffer); 100 : ReturnErrorOnFailure(hash.Begin()); 101 : ReturnErrorOnFailure(hash.AddData(params.rotatingDeviceIdUniqueId)); 102 : ReturnErrorOnFailure(hash.AddData(ByteSpan{ lifetimeCounterBuffer, sizeof(params.rotatingDeviceIdLifetimeCounter) })); 103 : ReturnErrorOnFailure(hash.Finish(hashOutputSpan)); 104 : 105 : outputBufferWriter.Put16(params.rotatingDeviceIdLifetimeCounter); 106 : outputBufferWriter.Put(&hashOutputBuffer[kSHA256_Hash_Length - RotatingDeviceId::kHashSuffixLength], 107 : RotatingDeviceId::kHashSuffixLength); 108 : VerifyOrReturnError(outputBufferWriter.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL); 109 : rotatingDeviceIdBuffer.reduce_size(outputBufferWriter.Needed()); 110 : return CHIP_NO_ERROR; 111 : } 112 : 113 : CHIP_ERROR AdditionalDataPayloadGenerator::generateRotatingDeviceIdAsHexString(AdditionalDataPayloadGeneratorParams & params, 114 : char * rotatingDeviceIdBuffer, 115 : size_t rotatingDeviceIdBufferSize, 116 : size_t & rotatingDeviceIdValueOutputSize) 117 : { 118 : uint8_t rotatingDeviceIdInternalBuffer[RotatingDeviceId::kMaxLength]; 119 : MutableByteSpan rotatingDeviceIdBufferTemp(rotatingDeviceIdInternalBuffer); 120 : ReturnErrorOnFailure(generateRotatingDeviceIdAsBinary(params, rotatingDeviceIdBufferTemp)); 121 : 122 : VerifyOrReturnError(rotatingDeviceIdBufferSize >= RotatingDeviceId::kHexMaxLength, CHIP_ERROR_BUFFER_TOO_SMALL); 123 : ReturnErrorOnFailure(BytesToUppercaseHexString(rotatingDeviceIdBufferTemp.data(), rotatingDeviceIdBufferTemp.size(), 124 : rotatingDeviceIdBuffer, rotatingDeviceIdBufferSize)); 125 : rotatingDeviceIdValueOutputSize = rotatingDeviceIdBufferTemp.size() * 2; 126 : return CHIP_NO_ERROR; 127 : } 128 : #endif