3 * Copyright (c) 2021 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * This file provides a utility to generate Additional Data payload and its members
21 * (e.g. rotating device id)
25 #include "AdditionalDataPayloadGenerator.h"
26 #include "AdditionalDataPayload.h"
28 #include <core/CHIPCore.h>
29 #include <core/CHIPEncoding.h>
30 #include <core/CHIPSafeCasts.h>
31 #include <core/CHIPTLV.h>
32 #include <crypto/CHIPCryptoPAL.h>
34 #include <support/BufferWriter.h>
35 #include <support/CHIPMem.h>
38 using namespace chip::System;
39 using namespace chip::TLV;
40 using namespace chip::Crypto;
41 using namespace chip::SetupPayloadData;
42 using namespace chip::Encoding::LittleEndian;
45 AdditionalDataPayloadGenerator::generateAdditionalDataPayload(uint16_t lifetimeCounter, const char * serialNumberBuffer,
46 size_t serialNumberBufferSize, PacketBufferHandle & bufferHandle,
47 BitFlags<uint8_t, AdditionalDataFields> additionalDataFields)
49 CHIP_ERROR err = CHIP_NO_ERROR;
50 System::PacketBufferTLVWriter writer;
51 TLVWriter innerWriter;
52 char rotatingDeviceIdBuffer[RotatingDeviceId::kHexMaxLength];
53 size_t rotatingDeviceIdBufferSize = 0;
55 // Initialize TLVWriter
56 writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
58 SuccessOrExit(err = writer.OpenContainer(AnonymousTag, kTLVType_Structure, innerWriter));
60 if (additionalDataFields.Has(AdditionalDataFields::RotatingDeviceId))
62 // Generating Device Rotating Id
63 SuccessOrExit(err = generateRotatingDeviceId(lifetimeCounter, serialNumberBuffer, serialNumberBufferSize,
64 rotatingDeviceIdBuffer, ArraySize(rotatingDeviceIdBuffer),
65 rotatingDeviceIdBufferSize));
67 // Adding the rotating device id to the TLV data
68 SuccessOrExit(err = innerWriter.PutString(ContextTag(kRotatingDeviceIdTag), rotatingDeviceIdBuffer,
69 static_cast<uint32_t>(rotatingDeviceIdBufferSize)));
72 SuccessOrExit(err = writer.CloseContainer(innerWriter));
74 SuccessOrExit(err = writer.Finalize(&bufferHandle));
80 CHIP_ERROR AdditionalDataPayloadGenerator::generateRotatingDeviceId(uint16_t lifetimeCounter, const char * serialNumberBuffer,
81 size_t serialNumberBufferSize, char rotatingDeviceIdBuffer[],
82 size_t rotatingDeviceIdBufferSize,
83 size_t & rotatingDeviceIdValueOutputSize)
85 CHIP_ERROR err = CHIP_NO_ERROR;
86 Hash_SHA256_stream hash;
87 uint8_t outputBuffer[RotatingDeviceId::kMaxLength];
88 uint8_t hashOutputBuffer[kSHA256_Hash_Length];
89 BufferWriter outputBufferWriter(outputBuffer, ArraySize(outputBuffer));
90 size_t rotatingDeviceIdBufferIndex = 0;
91 uint8_t lifetimeCounterBuffer[2];
93 Put16(lifetimeCounterBuffer, lifetimeCounter);
95 VerifyOrExit(rotatingDeviceIdBufferSize >= RotatingDeviceId::kHexMaxLength, err = CHIP_ERROR_BUFFER_TOO_SMALL);
97 // Computing the Rotating Device Id
98 // RDI = Lifetime_Counter + SuffixBytes(SHA256(Serial_Number + Lifetime_Counter), 16)
100 SuccessOrExit(err = hash.Begin());
101 SuccessOrExit(err = hash.AddData(Uint8::from_const_char(serialNumberBuffer), serialNumberBufferSize));
102 SuccessOrExit(err = hash.AddData(lifetimeCounterBuffer, sizeof(lifetimeCounter)));
103 SuccessOrExit(err = hash.Finish(hashOutputBuffer));
105 outputBufferWriter.Put16(lifetimeCounter);
106 outputBufferWriter.Put(&hashOutputBuffer[kSHA256_Hash_Length - RotatingDeviceId::kHashSuffixLength],
107 RotatingDeviceId::kHashSuffixLength);
109 for (rotatingDeviceIdBufferIndex = 0; rotatingDeviceIdBufferIndex < outputBufferWriter.Needed(); rotatingDeviceIdBufferIndex++)
111 snprintf(&rotatingDeviceIdBuffer[rotatingDeviceIdBufferIndex * 2],
112 rotatingDeviceIdBufferSize - rotatingDeviceIdBufferIndex * 2, "%02X",
113 outputBufferWriter.Buffer()[rotatingDeviceIdBufferIndex]);
116 rotatingDeviceIdBuffer[rotatingDeviceIdBufferIndex * 2] = 0;
117 rotatingDeviceIdValueOutputSize = rotatingDeviceIdBufferIndex * 2;
118 ChipLogDetail(DeviceLayer, "rotatingDeviceId: %s", rotatingDeviceIdBuffer);