5e6d99024dca2344591e89f37c0212ad3748b778
[platform/upstream/connectedhomeip.git] / src / setup_payload / AdditionalDataPayloadGenerator.cpp
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 <core/CHIPCore.h>
29 #include <core/CHIPEncoding.h>
30 #include <core/CHIPSafeCasts.h>
31 #include <core/CHIPTLV.h>
32 #include <crypto/CHIPCryptoPAL.h>
33 #include <stdlib.h>
34 #include <support/BufferWriter.h>
35 #include <support/CHIPMem.h>
36
37 using namespace chip;
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;
43
44 CHIP_ERROR
45 AdditionalDataPayloadGenerator::generateAdditionalDataPayload(uint16_t lifetimeCounter, const char * serialNumberBuffer,
46                                                               size_t serialNumberBufferSize, PacketBufferHandle & bufferHandle,
47                                                               BitFlags<uint8_t, AdditionalDataFields> additionalDataFields)
48 {
49     CHIP_ERROR err = CHIP_NO_ERROR;
50     System::PacketBufferTLVWriter writer;
51     TLVWriter innerWriter;
52     char rotatingDeviceIdBuffer[RotatingDeviceId::kHexMaxLength];
53     size_t rotatingDeviceIdBufferSize = 0;
54
55     // Initialize TLVWriter
56     writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
57
58     SuccessOrExit(err = writer.OpenContainer(AnonymousTag, kTLVType_Structure, innerWriter));
59
60     if (additionalDataFields.Has(AdditionalDataFields::RotatingDeviceId))
61     {
62         // Generating Device Rotating Id
63         SuccessOrExit(err = generateRotatingDeviceId(lifetimeCounter, serialNumberBuffer, serialNumberBufferSize,
64                                                      rotatingDeviceIdBuffer, ArraySize(rotatingDeviceIdBuffer),
65                                                      rotatingDeviceIdBufferSize));
66
67         // Adding the rotating device id to the TLV data
68         SuccessOrExit(err = innerWriter.PutString(ContextTag(kRotatingDeviceIdTag), rotatingDeviceIdBuffer,
69                                                   static_cast<uint32_t>(rotatingDeviceIdBufferSize)));
70     }
71
72     SuccessOrExit(err = writer.CloseContainer(innerWriter));
73
74     SuccessOrExit(err = writer.Finalize(&bufferHandle));
75
76 exit:
77     return err;
78 }
79
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)
84 {
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];
92
93     Put16(lifetimeCounterBuffer, lifetimeCounter);
94
95     VerifyOrExit(rotatingDeviceIdBufferSize >= RotatingDeviceId::kHexMaxLength, err = CHIP_ERROR_BUFFER_TOO_SMALL);
96
97     // Computing the Rotating Device Id
98     // RDI = Lifetime_Counter + SuffixBytes(SHA256(Serial_Number + Lifetime_Counter), 16)
99
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));
104
105     outputBufferWriter.Put16(lifetimeCounter);
106     outputBufferWriter.Put(&hashOutputBuffer[kSHA256_Hash_Length - RotatingDeviceId::kHashSuffixLength],
107                            RotatingDeviceId::kHashSuffixLength);
108
109     for (rotatingDeviceIdBufferIndex = 0; rotatingDeviceIdBufferIndex < outputBufferWriter.Needed(); rotatingDeviceIdBufferIndex++)
110     {
111         snprintf(&rotatingDeviceIdBuffer[rotatingDeviceIdBufferIndex * 2],
112                  rotatingDeviceIdBufferSize - rotatingDeviceIdBufferIndex * 2, "%02X",
113                  outputBufferWriter.Buffer()[rotatingDeviceIdBufferIndex]);
114     }
115
116     rotatingDeviceIdBuffer[rotatingDeviceIdBufferIndex * 2] = 0;
117     rotatingDeviceIdValueOutputSize                         = rotatingDeviceIdBufferIndex * 2;
118     ChipLogDetail(DeviceLayer, "rotatingDeviceId: %s", rotatingDeviceIdBuffer);
119
120 exit:
121     return err;
122 }