| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- *
- * Copyright (c) 2022 Project CHIP Authors
- * All rights reserved.
- *
- * 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.
- */
- #include "Options.h"
- #include <algorithm>
- #include <app-common/zap-generated/cluster-objects.h>
- #include <app/data-model/Encode.h>
- #include <credentials/DeviceAttestationConstructor.h>
- #include <crypto/CHIPCryptoPAL.h>
- using namespace chip;
- using namespace chip::app;
- using namespace chip::app::Clusters::OperationalCredentials::Commands;
- constexpr size_t kMaxResponseLength = 900;
- constexpr size_t kCSRNonceLength = 32;
- namespace {
- CHIP_ERROR ConstructCustomNOCSRElements(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & nocsrElements,
- CSRResponseOptions & options)
- {
- ByteSpan csr;
- ByteSpan csrNonce;
- ByteSpan vendorReserved1;
- ByteSpan vendorReserved2;
- ByteSpan vendorReserved3;
- ReturnErrorOnFailure(
- Credentials::DeconstructNOCSRElements(nocsrElements, csr, csrNonce, vendorReserved1, vendorReserved2, vendorReserved3));
- // Add 10 bytes of possible overhead to allow the generation of content longer than the allowed maximum of RESP_MAX.
- // 10 has been choosen to leave enough space for the possible TLV overhead when adding the additional data.
- uint8_t nocsrElementsData[kMaxResponseLength + 10];
- MutableByteSpan nocsrElementsSpan(nocsrElementsData);
- TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
- TLV::TLVWriter tlvWriter;
- tlvWriter.Init(nocsrElementsSpan);
- ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
- // Update CSR
- if (options.csrIncorrectType)
- {
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), true));
- }
- else
- {
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), csr));
- }
- // Update CSRNonce
- if (options.csrNonceIncorrectType)
- {
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), true));
- }
- else if (options.csrNonceInvalid)
- {
- uint8_t csrNonceInvalid[kCSRNonceLength] = {};
- memcpy(csrNonceInvalid, csrNonce.data(), csrNonce.size());
- std::reverse(csrNonceInvalid, csrNonceInvalid + sizeof(csrNonceInvalid));
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceInvalid)));
- }
- else if (options.csrNonceTooLong)
- {
- uint8_t csrNonceTooLong[kCSRNonceLength + 1] = {};
- memcpy(csrNonceTooLong, csrNonce.data(), csrNonce.size());
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceTooLong)));
- }
- else
- {
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), csrNonce));
- }
- // Add vendorReserved1 if present
- if (!vendorReserved1.empty())
- {
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), vendorReserved1));
- }
- // Add vendorReserved2 if present
- if (!vendorReserved2.empty())
- {
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(4), vendorReserved2));
- }
- // Add vendorReserved3 if present
- if (!vendorReserved3.empty())
- {
- ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(5), vendorReserved3));
- }
- // Add additional data
- if (options.nocsrElementsTooLong)
- {
- size_t len = kMaxResponseLength - tlvWriter.GetLengthWritten();
- ReturnLogErrorOnFailure(tlvWriter.Put(TLV::ContextTag(6), ByteSpan(nocsrElementsData, len)));
- }
- ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
- ReturnErrorOnFailure(tlvWriter.Finalize());
- return DataModel::Encode(writer, tag, nocsrElementsSpan.SubSpan(0, tlvWriter.GetLengthWritten()));
- }
- CHIP_ERROR ConstructCustomAttestationSignature(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & attestationSignature,
- CSRResponseOptions & options)
- {
- if (options.attestationSignatureIncorrectType)
- {
- return DataModel::Encode(writer, tag, true);
- }
- if (options.attestationSignatureInvalid)
- {
- uint8_t invalidAttestationSignature[Crypto::kP256_ECDSA_Signature_Length_Raw] = {};
- memcpy(invalidAttestationSignature, attestationSignature.data(), attestationSignature.size());
- std::reverse(invalidAttestationSignature, invalidAttestationSignature + sizeof(invalidAttestationSignature));
- return DataModel::Encode(writer, tag, ByteSpan(invalidAttestationSignature));
- }
- return DataModel::Encode(writer, tag, attestationSignature);
- }
- } // namespace
- namespace chip {
- namespace app {
- namespace DataModel {
- template <>
- CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const CSRResponse::Type & responseData)
- {
- auto tag1 = TLV::ContextTag(CSRResponse::Fields::kNOCSRElements);
- auto tag2 = TLV::ContextTag(CSRResponse::Fields::kAttestationSignature);
- auto & options = LinuxDeviceOptions::GetInstance().mCSRResponseOptions;
- TLV::TLVType outer;
- ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
- ReturnErrorOnFailure(ConstructCustomNOCSRElements(writer, tag1, responseData.NOCSRElements, options));
- ReturnErrorOnFailure(ConstructCustomAttestationSignature(writer, tag2, responseData.attestationSignature, options));
- ReturnErrorOnFailure(writer.EndContainer(outer));
- return CHIP_NO_ERROR;
- }
- } // namespace DataModel
- } // namespace app
- } // namespace chip
|