/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 |