CustomCSRResponse.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. *
  3. * Copyright (c) 2022 Project CHIP Authors
  4. * All rights reserved.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #include "Options.h"
  19. #include <algorithm>
  20. #include <app-common/zap-generated/cluster-objects.h>
  21. #include <app/data-model/Encode.h>
  22. #include <credentials/DeviceAttestationConstructor.h>
  23. #include <crypto/CHIPCryptoPAL.h>
  24. using namespace chip;
  25. using namespace chip::app;
  26. using namespace chip::app::Clusters::OperationalCredentials::Commands;
  27. constexpr size_t kMaxResponseLength = 900;
  28. constexpr size_t kCSRNonceLength = 32;
  29. namespace {
  30. CHIP_ERROR ConstructCustomNOCSRElements(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & nocsrElements,
  31. CSRResponseOptions & options)
  32. {
  33. ByteSpan csr;
  34. ByteSpan csrNonce;
  35. ByteSpan vendorReserved1;
  36. ByteSpan vendorReserved2;
  37. ByteSpan vendorReserved3;
  38. ReturnErrorOnFailure(
  39. Credentials::DeconstructNOCSRElements(nocsrElements, csr, csrNonce, vendorReserved1, vendorReserved2, vendorReserved3));
  40. // Add 10 bytes of possible overhead to allow the generation of content longer than the allowed maximum of RESP_MAX.
  41. // 10 has been choosen to leave enough space for the possible TLV overhead when adding the additional data.
  42. uint8_t nocsrElementsData[kMaxResponseLength + 10];
  43. MutableByteSpan nocsrElementsSpan(nocsrElementsData);
  44. TLV::TLVType outerContainerType = TLV::kTLVType_NotSpecified;
  45. TLV::TLVWriter tlvWriter;
  46. tlvWriter.Init(nocsrElementsSpan);
  47. ReturnErrorOnFailure(tlvWriter.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType));
  48. // Update CSR
  49. if (options.csrIncorrectType)
  50. {
  51. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), true));
  52. }
  53. else
  54. {
  55. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(1), csr));
  56. }
  57. // Update CSRNonce
  58. if (options.csrNonceIncorrectType)
  59. {
  60. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), true));
  61. }
  62. else if (options.csrNonceInvalid)
  63. {
  64. uint8_t csrNonceInvalid[kCSRNonceLength] = {};
  65. memcpy(csrNonceInvalid, csrNonce.data(), csrNonce.size());
  66. std::reverse(csrNonceInvalid, csrNonceInvalid + sizeof(csrNonceInvalid));
  67. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceInvalid)));
  68. }
  69. else if (options.csrNonceTooLong)
  70. {
  71. uint8_t csrNonceTooLong[kCSRNonceLength + 1] = {};
  72. memcpy(csrNonceTooLong, csrNonce.data(), csrNonce.size());
  73. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), ByteSpan(csrNonceTooLong)));
  74. }
  75. else
  76. {
  77. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(2), csrNonce));
  78. }
  79. // Add vendorReserved1 if present
  80. if (!vendorReserved1.empty())
  81. {
  82. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(3), vendorReserved1));
  83. }
  84. // Add vendorReserved2 if present
  85. if (!vendorReserved2.empty())
  86. {
  87. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(4), vendorReserved2));
  88. }
  89. // Add vendorReserved3 if present
  90. if (!vendorReserved3.empty())
  91. {
  92. ReturnErrorOnFailure(tlvWriter.Put(TLV::ContextTag(5), vendorReserved3));
  93. }
  94. // Add additional data
  95. if (options.nocsrElementsTooLong)
  96. {
  97. size_t len = kMaxResponseLength - tlvWriter.GetLengthWritten();
  98. ReturnLogErrorOnFailure(tlvWriter.Put(TLV::ContextTag(6), ByteSpan(nocsrElementsData, len)));
  99. }
  100. ReturnErrorOnFailure(tlvWriter.EndContainer(outerContainerType));
  101. ReturnErrorOnFailure(tlvWriter.Finalize());
  102. return DataModel::Encode(writer, tag, nocsrElementsSpan.SubSpan(0, tlvWriter.GetLengthWritten()));
  103. }
  104. CHIP_ERROR ConstructCustomAttestationSignature(TLV::TLVWriter & writer, TLV::Tag tag, const ByteSpan & attestationSignature,
  105. CSRResponseOptions & options)
  106. {
  107. if (options.attestationSignatureIncorrectType)
  108. {
  109. return DataModel::Encode(writer, tag, true);
  110. }
  111. if (options.attestationSignatureInvalid)
  112. {
  113. uint8_t invalidAttestationSignature[Crypto::kP256_ECDSA_Signature_Length_Raw] = {};
  114. memcpy(invalidAttestationSignature, attestationSignature.data(), attestationSignature.size());
  115. std::reverse(invalidAttestationSignature, invalidAttestationSignature + sizeof(invalidAttestationSignature));
  116. return DataModel::Encode(writer, tag, ByteSpan(invalidAttestationSignature));
  117. }
  118. return DataModel::Encode(writer, tag, attestationSignature);
  119. }
  120. } // namespace
  121. namespace chip {
  122. namespace app {
  123. namespace DataModel {
  124. template <>
  125. CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, const CSRResponse::Type & responseData)
  126. {
  127. auto tag1 = TLV::ContextTag(CSRResponse::Fields::kNOCSRElements);
  128. auto tag2 = TLV::ContextTag(CSRResponse::Fields::kAttestationSignature);
  129. auto & options = LinuxDeviceOptions::GetInstance().mCSRResponseOptions;
  130. TLV::TLVType outer;
  131. ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
  132. ReturnErrorOnFailure(ConstructCustomNOCSRElements(writer, tag1, responseData.NOCSRElements, options));
  133. ReturnErrorOnFailure(ConstructCustomAttestationSignature(writer, tag2, responseData.attestationSignature, options));
  134. ReturnErrorOnFailure(writer.EndContainer(outer));
  135. return CHIP_NO_ERROR;
  136. }
  137. } // namespace DataModel
  138. } // namespace app
  139. } // namespace chip