Coverage Report

Created: 2026-06-30 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/connectedhomeip/src/setup_payload/AdditionalDataPayloadGenerator.cpp
Line
Count
Source
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
AdditionalDataPayloadGenerator::generateAdditionalDataPayload(AdditionalDataPayloadGeneratorParams & params,
49
                                                              PacketBufferHandle & bufferHandle,
50
                                                              BitFlags<AdditionalDataFields> additionalDataFields)
51
0
{
52
0
    System::PacketBufferTLVWriter writer;
53
0
    TLVWriter innerWriter;
54
55
    // Initialize TLVWriter
56
0
    auto tempBuffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize);
57
0
    VerifyOrReturnError(!tempBuffer.IsNull(), CHIP_ERROR_NO_MEMORY);
58
0
    writer.Init(std::move(tempBuffer));
59
60
0
    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
0
    ReturnErrorOnFailure(writer.CloseContainer(innerWriter));
76
77
0
    return writer.Finalize(&bufferHandle);
78
0
}
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