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
|