LinuxCommissionableDataProvider.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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 "LinuxCommissionableDataProvider.h"
  19. #include <string.h>
  20. #include <crypto/CHIPCryptoPAL.h>
  21. #include <lib/support/CodeUtils.h>
  22. #include <lib/support/Span.h>
  23. #include <lib/support/logging/CHIPLogging.h>
  24. using namespace chip::Crypto;
  25. namespace {
  26. CHIP_ERROR GeneratePaseSalt(std::vector<uint8_t> & spake2pSaltVector)
  27. {
  28. constexpr size_t kSaltLen = kSpake2p_Max_PBKDF_Salt_Length;
  29. spake2pSaltVector.resize(kSaltLen);
  30. return DRBG_get_bytes(spake2pSaltVector.data(), spake2pSaltVector.size());
  31. }
  32. } // namespace
  33. CHIP_ERROR LinuxCommissionableDataProvider::Init(chip::Optional<std::vector<uint8_t>> serializedSpake2pVerifier,
  34. chip::Optional<std::vector<uint8_t>> spake2pSalt, uint32_t spake2pIterationCount,
  35. chip::Optional<uint32_t> setupPasscode, uint16_t discriminator)
  36. {
  37. VerifyOrReturnError(mIsInitialized == false, CHIP_ERROR_WELL_UNINITIALIZED);
  38. if (discriminator > chip::kMaxDiscriminatorValue)
  39. {
  40. ChipLogError(Support, "Discriminator value invalid: %u", static_cast<unsigned>(discriminator));
  41. return CHIP_ERROR_INVALID_ARGUMENT;
  42. }
  43. if ((spake2pIterationCount < kSpake2p_Min_PBKDF_Iterations) || (spake2pIterationCount > kSpake2p_Max_PBKDF_Iterations))
  44. {
  45. ChipLogError(Support, "PASE Iteration count invalid: %u", static_cast<unsigned>(spake2pIterationCount));
  46. return CHIP_ERROR_INVALID_ARGUMENT;
  47. }
  48. bool havePaseVerifier = serializedSpake2pVerifier.HasValue();
  49. Spake2pVerifier providedVerifier;
  50. CHIP_ERROR err;
  51. std::vector<uint8_t> finalSerializedVerifier(kSpake2p_VerifierSerialized_Length);
  52. if (havePaseVerifier)
  53. {
  54. if (serializedSpake2pVerifier.Value().size() != kSpake2p_VerifierSerialized_Length)
  55. {
  56. ChipLogError(Support, "PASE verifier size invalid: %u",
  57. static_cast<unsigned>(serializedSpake2pVerifier.Value().size()));
  58. return CHIP_ERROR_INVALID_ARGUMENT;
  59. }
  60. chip::MutableByteSpan verifierSpan{ serializedSpake2pVerifier.Value().data(), serializedSpake2pVerifier.Value().size() };
  61. err = providedVerifier.Deserialize(verifierSpan);
  62. if (err != CHIP_NO_ERROR)
  63. {
  64. ChipLogError(Support, "Failed to deserialized PASE verifier: %" CHIP_ERROR_FORMAT, err.Format());
  65. return err;
  66. }
  67. ChipLogProgress(Support, "Got externally provided verifier, using it.");
  68. }
  69. bool havePaseSalt = spake2pSalt.HasValue();
  70. if (havePaseVerifier && !havePaseSalt)
  71. {
  72. ChipLogError(Support, "LinuxCommissionableDataProvider didn't get a PASE salt, but got a verifier: ambiguous data");
  73. return CHIP_ERROR_INVALID_ARGUMENT;
  74. }
  75. size_t spake2pSaltLength = havePaseSalt ? spake2pSalt.Value().size() : 0;
  76. if (havePaseSalt &&
  77. ((spake2pSaltLength < kSpake2p_Min_PBKDF_Salt_Length) || (spake2pSaltLength > kSpake2p_Max_PBKDF_Salt_Length)))
  78. {
  79. ChipLogError(Support, "PASE salt length invalid: %u", static_cast<unsigned>(spake2pSaltLength));
  80. return CHIP_ERROR_INVALID_ARGUMENT;
  81. }
  82. if (!havePaseSalt)
  83. {
  84. ChipLogProgress(Support, "LinuxCommissionableDataProvider didn't get a PASE salt, generating one.");
  85. std::vector<uint8_t> spake2pSaltVector;
  86. err = GeneratePaseSalt(spake2pSaltVector);
  87. if (err != CHIP_NO_ERROR)
  88. {
  89. ChipLogError(Support, "Failed to generate PASE salt: %" CHIP_ERROR_FORMAT, err.Format());
  90. return err;
  91. }
  92. spake2pSalt.SetValue(std::move(spake2pSaltVector));
  93. }
  94. bool havePasscode = setupPasscode.HasValue();
  95. Spake2pVerifier passcodeVerifier;
  96. std::vector<uint8_t> serializedPasscodeVerifier(kSpake2p_VerifierSerialized_Length);
  97. chip::MutableByteSpan saltSpan{ spake2pSalt.Value().data(), spake2pSalt.Value().size() };
  98. if (havePasscode)
  99. {
  100. err = passcodeVerifier.Generate(spake2pIterationCount, saltSpan, setupPasscode.Value());
  101. if (err != CHIP_NO_ERROR)
  102. {
  103. ChipLogError(Support, "Failed to generate PASE verifier from passcode: %" CHIP_ERROR_FORMAT, err.Format());
  104. return err;
  105. }
  106. chip::MutableByteSpan verifierSpan{ serializedPasscodeVerifier.data(), serializedPasscodeVerifier.size() };
  107. err = passcodeVerifier.Serialize(verifierSpan);
  108. if (err != CHIP_NO_ERROR)
  109. {
  110. ChipLogError(Support, "Failed to serialize PASE verifier from passcode: %" CHIP_ERROR_FORMAT, err.Format());
  111. return err;
  112. }
  113. }
  114. // Make sure we actually have a verifier
  115. if (!havePasscode && !havePaseVerifier)
  116. {
  117. ChipLogError(Support, "Missing both externally provided verifier and passcode: cannot produce final verifier");
  118. return CHIP_ERROR_INVALID_ARGUMENT;
  119. }
  120. // If both passcode and external verifier were provided, validate they match, otherwise
  121. // it's ambiguous.
  122. if (havePasscode && havePaseVerifier)
  123. {
  124. if (serializedPasscodeVerifier != serializedSpake2pVerifier.Value())
  125. {
  126. ChipLogError(Support, "Mismatching verifier between passcode and external verifier. Validate inputs.");
  127. return CHIP_ERROR_INVALID_ARGUMENT;
  128. }
  129. ChipLogProgress(Support, "Validated externally provided passcode matches the one generated from provided passcode.");
  130. }
  131. // External PASE verifier takes precedence when present (even though it is identical to passcode-based
  132. // one when the latter is present).
  133. if (havePaseVerifier)
  134. {
  135. finalSerializedVerifier = serializedSpake2pVerifier.Value();
  136. }
  137. else
  138. {
  139. finalSerializedVerifier = serializedPasscodeVerifier;
  140. }
  141. mDiscriminator = discriminator;
  142. mSerializedPaseVerifier = std::move(finalSerializedVerifier);
  143. mPaseSalt = std::move(spake2pSalt.Value());
  144. mPaseIterationCount = spake2pIterationCount;
  145. if (havePasscode)
  146. {
  147. mSetupPasscode.SetValue(setupPasscode.Value());
  148. }
  149. mIsInitialized = true;
  150. return CHIP_NO_ERROR;
  151. }
  152. CHIP_ERROR LinuxCommissionableDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator)
  153. {
  154. VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_WELL_UNINITIALIZED);
  155. setupDiscriminator = mDiscriminator;
  156. return CHIP_NO_ERROR;
  157. }
  158. CHIP_ERROR LinuxCommissionableDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount)
  159. {
  160. VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_WELL_UNINITIALIZED);
  161. iterationCount = mPaseIterationCount;
  162. return CHIP_NO_ERROR;
  163. }
  164. CHIP_ERROR LinuxCommissionableDataProvider::GetSpake2pSalt(chip::MutableByteSpan & saltBuf)
  165. {
  166. VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_WELL_UNINITIALIZED);
  167. VerifyOrReturnError(saltBuf.size() >= kSpake2p_Max_PBKDF_Salt_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
  168. memcpy(saltBuf.data(), mPaseSalt.data(), mPaseSalt.size());
  169. saltBuf.reduce_size(mPaseSalt.size());
  170. return CHIP_NO_ERROR;
  171. }
  172. CHIP_ERROR LinuxCommissionableDataProvider::GetSpake2pVerifier(chip::MutableByteSpan & verifierBuf, size_t & outVerifierLen)
  173. {
  174. VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_WELL_UNINITIALIZED);
  175. // By now, serialized verifier from Init should be correct size
  176. VerifyOrReturnError(mSerializedPaseVerifier.size() == kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INTERNAL);
  177. outVerifierLen = mSerializedPaseVerifier.size();
  178. VerifyOrReturnError(verifierBuf.size() >= outVerifierLen, CHIP_ERROR_BUFFER_TOO_SMALL);
  179. memcpy(verifierBuf.data(), mSerializedPaseVerifier.data(), mSerializedPaseVerifier.size());
  180. verifierBuf.reduce_size(mSerializedPaseVerifier.size());
  181. return CHIP_NO_ERROR;
  182. }
  183. CHIP_ERROR LinuxCommissionableDataProvider::GetSetupPasscode(uint32_t & setupPasscode)
  184. {
  185. VerifyOrReturnError(mIsInitialized == true, CHIP_ERROR_WELL_UNINITIALIZED);
  186. // Pretend not implemented if we don't have a passcode value externally set
  187. if (!mSetupPasscode.HasValue())
  188. {
  189. return CHIP_ERROR_NOT_IMPLEMENTED;
  190. }
  191. setupPasscode = mSetupPasscode.Value();
  192. return CHIP_NO_ERROR;
  193. }