Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device Attestation helpers #3

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/credentials/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ static_library("credentials") {
"CHIPOperationalCredentials.h",
"DeviceAttestationCredsProvider.cpp",
"DeviceAttestationCredsProvider.h",
"DeviceAttestation.h",
"DeviceAttestation.cpp",
"GenerateChipX509Cert.cpp",
"examples/DeviceAttestationCredsExample.cpp",
"examples/DeviceAttestationCredsExample.h",
Expand Down
146 changes: 146 additions & 0 deletions src/credentials/DeviceAttestation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include "DeviceAttestation.h"
#include <core/CHIPTLV.h>
#include <support/CodeUtils.h>

namespace chip {
namespace Credentials {

// TODO: vendor data needs fully qualitified IDs -- (vendor ID, profile number, tag #)


// context tag positions
enum { CERTIFICATE_DECLARATION = 1,
ATTESTATION_NONCE = 2,
TIMESTAMP = 3,
FIRMWARE_INFO = 4,
LAST_TAG = FIRMWARE_INFO
};

CHIP_ERROR DeconstructAttestationElements(const ByteSpan & attestationElements,
ByteSpan & certificationDeclaration,
ByteSpan & attestationNonce, uint32_t & timestamp, ByteSpan & firmwareInfo,
std::vector<ByteSpan> & vendorReserved,
uint16_t & vendorId, uint16_t & profileNum)
{
#if 0
ByteSpan * element_array[] = { &certificationDeclaration, &attestationNonce,
nullptr, /* timestamp */
&firmwareInfo,
};
#endif

uint32_t validArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool argExists[4] = { false }; // only check the first 4 elements
CHIP_ERROR TLVError = CHIP_NO_ERROR;
TLV::TLVReader tlvReader;
TLV::TLVType containerType = TLV::kTLVType_Structure;

tlvReader.Init(attestationElements.data(), static_cast<uint32_t>(attestationElements.size()));
ReturnErrorOnFailure(tlvReader.Next(containerType, TLV::AnonymousTag));
ReturnErrorOnFailure(tlvReader.EnterContainer(containerType));

while ((TLVError = tlvReader.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
uint64_t tag;

tag = tlvReader.GetTag();

if (TLV::IsContextTag(tag))
{
currentDecodeTagId = TLV::TagNumFromTag(tag);
if(0 == currentDecodeTagId)
continue; // ignore tag 0? or error?
if(currentDecodeTagId > LAST_TAG)
continue; // ignore tags too high? or error
if(true == argExists[currentDecodeTagId - 1])
return CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
argExists[currentDecodeTagId - 1] = true;
validArgumentCount++;

const uint8_t *data = nullptr;
// TODO: helper routine for cases 1, 3, 4 -- CHIP_ERROR getByteSpan(field &, tlvReader)
switch(currentDecodeTagId) {
case CERTIFICATE_DECLARATION:
// if(nullptr == certificationDeclaration)
// break;
VerifyOrReturnError(tlvReader.GetDataPtr(data) != CHIP_NO_ERROR, CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT);
certificationDeclaration = ByteSpan(data, tlvReader.GetLength());
break;
case ATTESTATION_NONCE:
// if(nullptr == attestationNonce)
// break;
VerifyOrReturnError(tlvReader.GetDataPtr(data) != CHIP_NO_ERROR, CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT);
attestationNonce = ByteSpan(data, tlvReader.GetLength());
break;
case TIMESTAMP:
// if(nullptr == timestamp)
// break;
VerifyOrReturnError(tlvReader.Get(timestamp) != CHIP_NO_ERROR, CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT);
break;
case FIRMWARE_INFO:
// if(nullptr == firmwareInfo)
// break;
VerifyOrReturnError(tlvReader.GetDataPtr(data) != CHIP_NO_ERROR, CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT);
firmwareInfo = ByteSpan(data, tlvReader.GetLength());
break;
default:
// should never get here? Error?
return CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
}
} else if(TLV::IsProfileTag(tag)) {
// vendor information
} else {
// error
return CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
}
}

return CHIP_NO_ERROR;
}


CHIP_ERROR ConstructAttestationElements(const ByteSpan & certificationDeclaration, const ByteSpan & attestationNonce,
uint32_t timestamp, const ByteSpan & firmwareInfo,
std::vector<ByteSpan> &vendorReserved,
uint16_t vendorId, uint16_t profileNum,
MutableByteSpan & attestationElements )
{
TLV::TLVWriter tlvWriter;
TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;

tlvWriter.Init(attestationElements.data(), static_cast<uint32_t>(attestationElements.size()));
outerContainerType = TLV::kTLVType_NotSpecified;
ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag, TLV::kTLVType_Structure, outerContainerType));
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), certificationDeclaration));
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), attestationNonce));
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), timestamp));
if (!firmwareInfo.empty())
{
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(4), firmwareInfo));
}

// TODO: this has to be changed
#if 0
uint8_t tagNum = 5;
for(auto &vendorItem : vendorReserved) {
if(!vendorItem.empty())
{
ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(tagNum), vendorItem));
}
tagNum++;
}
#endif

ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
ReturnErrorOnFailure(tlvWriter.Finalize());
attestationElements = attestationElements.SubSpan(0, tlvWriter.GetLengthWritten());

return CHIP_NO_ERROR;
}


} // namespace Credentials

} // namespace chip
65 changes: 65 additions & 0 deletions src/credentials/DeviceAttestation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
*
* 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.
*/
#pragma once

#include <lib/core/CHIPError.h>
#include <lib/support/Span.h>
#include <vector>


namespace chip {
namespace Credentials {

/**
* @brief Take the attestation elements vector and return each component seperately.
*
* @param[in] attestionElements Buffer containg source of attestion
* @param[out] certificationDeclaration
* @param[out] attestationNonce
* @param[out] timestamp
* @param[out] firmwareInfo
* @param[out] vendorReserved elements
* @param[out] vendorId (from vendor reserved elements)
* @param[out] profileNum (from vendor reserved elements)
*/
CHIP_ERROR DeconstructAttestationElements(const ByteSpan & attestationElements, ByteSpan & certificationDeclaration,
ByteSpan & attestationNonce, uint32_t & timestamp, ByteSpan & firmwareInfo,
std::vector<ByteSpan> &vendorReserved, uint16_t & vendorId, uint16_t & profileNum );
// uint16_t & vendorId, uint16_t & profileNum );


/**
* @brief Take discrete components .
*
* @param[in] attestionElements Buffer containg source of attestion
* @param[out] certificationDeclaration
* @param[out] attestationNonce
* @param[out] timestamp
* @param[out] firmwareInfo
* @param[out] vendorReserved elements
* @param[out] vendorId (from vendor reserved elements)
* @param[out] profileNum (from vendor reserved elements)
*/

CHIP_ERROR ConstructAttestationElements(const ByteSpan & certificationDeclaration, const ByteSpan & attestationNonce,
uint32_t timestamp, const ByteSpan & firmwareInfo,
std::vector<ByteSpan> &vendorReserved, uint16_t vendorId, uint16_t profileNum,
MutableByteSpan & attestationElements);

} // namespace Credentials
} // namespace chip

1 change: 1 addition & 0 deletions src/credentials/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ chip_test_suite("tests") {
"TestChipCert.cpp",
"TestChipOperationalCredentials.cpp",
"TestDeviceAttestationCredentials.cpp",
"TestDeviceAttestationConstruction.cpp"
]

cflags = [ "-Wconversion" ]
Expand Down
Loading