blob: f223d1df4b9e3a8b94b67e66a097d3e15470df8c [file] [log] [blame]
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file provides a utility to generate Additional Data payload and its members
* (e.g. rotating device id)
*
*/
#include "AdditionalDataPayloadGenerator.h"
#include "AdditionalDataPayload.h"
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPEncoding.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/BufferWriter.h>
#include <lib/support/BytesToHex.h>
#include <lib/support/CHIPMem.h>
#include <stdlib.h>
using namespace chip;
using namespace chip::System;
using namespace chip::TLV;
using namespace chip::Crypto;
using namespace chip::SetupPayloadData;
using namespace chip::Encoding::LittleEndian;
using chip::Encoding::BytesToUppercaseHexString;
CHIP_ERROR
AdditionalDataPayloadGenerator::generateAdditionalDataPayload(AdditionalDataPayloadGeneratorParams & params,
PacketBufferHandle & bufferHandle,
BitFlags<AdditionalDataFields> additionalDataFields)
{
System::PacketBufferTLVWriter writer;
TLVWriter innerWriter;
// Initialize TLVWriter
auto tempBuffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize);
VerifyOrReturnError(!tempBuffer.IsNull(), CHIP_ERROR_NO_MEMORY);
writer.Init(std::move(tempBuffer));
ReturnErrorOnFailure(writer.OpenContainer(AnonymousTag(), kTLVType_Structure, innerWriter));
#if CHIP_ENABLE_ROTATING_DEVICE_ID
if (additionalDataFields.Has(AdditionalDataFields::RotatingDeviceId))
{
uint8_t rotatingDeviceIdInternalBuffer[RotatingDeviceId::kMaxLength];
MutableByteSpan rotatingDeviceIdBuffer(rotatingDeviceIdInternalBuffer);
// Generating Device Rotating Id
ReturnErrorOnFailure(generateRotatingDeviceIdAsBinary(params, rotatingDeviceIdBuffer));
// Adding the rotating device id to the TLV data
ReturnErrorOnFailure(innerWriter.Put(ContextTag(kRotatingDeviceIdTag), rotatingDeviceIdBuffer));
}
#endif
ReturnErrorOnFailure(writer.CloseContainer(innerWriter));
return writer.Finalize(&bufferHandle);
}
#if CHIP_ENABLE_ROTATING_DEVICE_ID
CHIP_ERROR AdditionalDataPayloadGenerator::generateRotatingDeviceIdAsBinary(AdditionalDataPayloadGeneratorParams & params,
MutableByteSpan & rotatingDeviceIdBuffer)
{
uint8_t hashOutputBuffer[kSHA256_Hash_Length];
BufferWriter outputBufferWriter(rotatingDeviceIdBuffer);
uint8_t lifetimeCounterBuffer[2];
if (params.rotatingDeviceIdUniqueId.data() == nullptr)
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
Put16(lifetimeCounterBuffer, params.rotatingDeviceIdLifetimeCounter);
// Computing the Rotating Device Id
// RDI = Lifetime_Counter + SuffixBytes(SHA256(Unique_Id + Lifetime_Counter), 16)
Hash_SHA256_stream hash;
MutableByteSpan hashOutputSpan(hashOutputBuffer);
ReturnErrorOnFailure(hash.Begin());
ReturnErrorOnFailure(hash.AddData(params.rotatingDeviceIdUniqueId));
ReturnErrorOnFailure(hash.AddData(ByteSpan{ lifetimeCounterBuffer, sizeof(params.rotatingDeviceIdLifetimeCounter) }));
ReturnErrorOnFailure(hash.Finish(hashOutputSpan));
outputBufferWriter.Put16(params.rotatingDeviceIdLifetimeCounter);
outputBufferWriter.Put(&hashOutputBuffer[kSHA256_Hash_Length - RotatingDeviceId::kHashSuffixLength],
RotatingDeviceId::kHashSuffixLength);
VerifyOrReturnError(outputBufferWriter.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL);
rotatingDeviceIdBuffer.reduce_size(outputBufferWriter.Needed());
return CHIP_NO_ERROR;
}
CHIP_ERROR AdditionalDataPayloadGenerator::generateRotatingDeviceIdAsHexString(AdditionalDataPayloadGeneratorParams & params,
char * rotatingDeviceIdBuffer,
size_t rotatingDeviceIdBufferSize,
size_t & rotatingDeviceIdValueOutputSize)
{
uint8_t rotatingDeviceIdInternalBuffer[RotatingDeviceId::kMaxLength];
MutableByteSpan rotatingDeviceIdBufferTemp(rotatingDeviceIdInternalBuffer);
ReturnErrorOnFailure(generateRotatingDeviceIdAsBinary(params, rotatingDeviceIdBufferTemp));
VerifyOrReturnError(rotatingDeviceIdBufferSize >= RotatingDeviceId::kHexMaxLength, CHIP_ERROR_BUFFER_TOO_SMALL);
ReturnErrorOnFailure(BytesToUppercaseHexString(rotatingDeviceIdBufferTemp.data(), rotatingDeviceIdBufferTemp.size(),
rotatingDeviceIdBuffer, rotatingDeviceIdBufferSize));
rotatingDeviceIdValueOutputSize = rotatingDeviceIdBufferTemp.size() * 2;
return CHIP_NO_ERROR;
}
#endif