|
| 1 | +// Copyright 2024 Google. All rights reserved. |
| 2 | +#pragma once |
| 3 | + |
| 4 | +#include <memory> |
| 5 | +#include <stddef.h> |
| 6 | +#include <stdint.h> |
| 7 | + |
| 8 | +#include "dm_dac.h" |
| 9 | +#include "dm_pai.h" |
| 10 | + |
| 11 | +#include <credentials/DeviceAttestationCredsProvider.h> |
| 12 | +#include <crypto/CHIPCryptoPAL.h> |
| 13 | +#include <include/platform/CommissionableDataProvider.h> |
| 14 | +#include <include/platform/DeviceInstanceInfoProvider.h> |
| 15 | +#include <lib/core/CHIPError.h> |
| 16 | +#include <lib/support/CHIPMemString.h> |
| 17 | +#include <lib/support/Span.h> |
| 18 | +#include <platform/CHIPDeviceConfig.h> |
| 19 | + |
| 20 | +// Should this all be in a header? No. Do I care? No. |
| 21 | + |
| 22 | +namespace google { |
| 23 | +namespace matter { |
| 24 | + |
| 25 | +class DrinkMachineInfoProvider : public chip::DeviceLayer::DeviceInstanceInfoProvider, |
| 26 | + public chip::DeviceLayer::CommissionableDataProvider |
| 27 | +{ |
| 28 | +public: |
| 29 | + // =============== DeviceInstanceInfoProvider interface ============= |
| 30 | + CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override |
| 31 | + { |
| 32 | + chip::Platform::CopyString(buf, bufSize, "Google LLC"); |
| 33 | + return CHIP_NO_ERROR; |
| 34 | + } |
| 35 | + |
| 36 | + CHIP_ERROR GetVendorId(uint16_t & vendorId) override |
| 37 | + { |
| 38 | + vendorId = 0x6006u; |
| 39 | + return CHIP_NO_ERROR; |
| 40 | + } |
| 41 | + |
| 42 | + CHIP_ERROR GetProductName(char * buf, size_t bufSize) override |
| 43 | + { |
| 44 | + chip::Platform::CopyString(buf, bufSize, "Disco Drink Machine"); |
| 45 | + return CHIP_NO_ERROR; |
| 46 | + } |
| 47 | + |
| 48 | + CHIP_ERROR GetProductId(uint16_t & productId) override |
| 49 | + { |
| 50 | + productId = 0xFFFEu; |
| 51 | + return CHIP_NO_ERROR; |
| 52 | + } |
| 53 | + CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override |
| 54 | + { |
| 55 | + chip::Platform::CopyString(buf, bufSize, "DDM-1"); |
| 56 | + return CHIP_NO_ERROR; |
| 57 | + } |
| 58 | + |
| 59 | + CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override |
| 60 | + { |
| 61 | + chip::Platform::CopyString(buf, bufSize, "https://google.com"); |
| 62 | + return CHIP_NO_ERROR; |
| 63 | + } |
| 64 | + |
| 65 | + CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override |
| 66 | + { |
| 67 | + chip::Platform::CopyString(buf, bufSize, "DiscoDrinkMachine"); |
| 68 | + return CHIP_NO_ERROR; |
| 69 | + } |
| 70 | + |
| 71 | + CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override |
| 72 | + { |
| 73 | + chip::Platform::CopyString(buf, bufSize, "0"); |
| 74 | + return CHIP_NO_ERROR; |
| 75 | + } |
| 76 | + |
| 77 | + CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override |
| 78 | + { |
| 79 | + year = 2024u; |
| 80 | + month = 10u; |
| 81 | + day = 24u; |
| 82 | + return CHIP_NO_ERROR; |
| 83 | + } |
| 84 | + CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override |
| 85 | + { |
| 86 | + hardwareVersion = 1; |
| 87 | + return CHIP_NO_ERROR; |
| 88 | + } |
| 89 | + |
| 90 | + CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override |
| 91 | + { |
| 92 | + chip::Platform::CopyString(buf, bufSize, "Custom"); |
| 93 | + return CHIP_NO_ERROR; |
| 94 | + } |
| 95 | + |
| 96 | + CHIP_ERROR GetRotatingDeviceIdUniqueId(chip::MutableByteSpan & uniqueIdSpan) override { return CHIP_ERROR_NOT_IMPLEMENTED; } |
| 97 | + // =============== CommissionableDataProvider interface ============= |
| 98 | + CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override |
| 99 | + { |
| 100 | + setupDiscriminator = mDiscriminator; |
| 101 | + return CHIP_NO_ERROR; |
| 102 | + } |
| 103 | + |
| 104 | + CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override |
| 105 | + { |
| 106 | + mDiscriminator = setupDiscriminator; |
| 107 | + return CHIP_NO_ERROR; |
| 108 | + } |
| 109 | + |
| 110 | + CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override |
| 111 | + { |
| 112 | + return mPreviousCommissionableDataProvider->GetSpake2pIterationCount(iterationCount); |
| 113 | + } |
| 114 | + |
| 115 | + CHIP_ERROR GetSpake2pSalt(chip::MutableByteSpan & saltBuf) override |
| 116 | + { |
| 117 | + return mPreviousCommissionableDataProvider->GetSpake2pSalt(saltBuf); |
| 118 | + } |
| 119 | + |
| 120 | + CHIP_ERROR GetSpake2pVerifier(chip::MutableByteSpan & verifierBuf, size_t & outVerifierLen) override |
| 121 | + { |
| 122 | + return mPreviousCommissionableDataProvider->GetSpake2pVerifier(verifierBuf, outVerifierLen); |
| 123 | + } |
| 124 | + |
| 125 | + CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override |
| 126 | + { |
| 127 | + // This needs to be the same because we're using the default pake verifier |
| 128 | + setupPasscode = 20202021; |
| 129 | + return CHIP_NO_ERROR; |
| 130 | + } |
| 131 | + |
| 132 | + CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override { return CHIP_ERROR_NOT_IMPLEMENTED; } |
| 133 | + |
| 134 | + // =============== Other public interface methods ============= |
| 135 | + void Register() |
| 136 | + { |
| 137 | + if (mPreviousCommissionableDataProvider == nullptr) |
| 138 | + { |
| 139 | + mPreviousCommissionableDataProvider = chip::DeviceLayer::GetCommissionableDataProvider(); |
| 140 | + chip::DeviceLayer::SetCommissionableDataProvider(this); |
| 141 | + } |
| 142 | + chip::DeviceLayer::SetDeviceInstanceInfoProvider(this); |
| 143 | + } |
| 144 | + |
| 145 | +private: |
| 146 | + chip::DeviceLayer::CommissionableDataProvider * mPreviousCommissionableDataProvider = nullptr; |
| 147 | + uint16_t mDiscriminator = 2233; |
| 148 | +}; |
| 149 | + |
| 150 | +class DrinkMachineCredentialsProvider : public chip::Credentials::DeviceAttestationCredentialsProvider |
| 151 | +{ |
| 152 | +public: |
| 153 | + CHIP_ERROR GetCertificationDeclaration(chip::MutableByteSpan & out_cd_buffer) override |
| 154 | + { |
| 155 | + // chip-cert gen-cd -C credentials/test/certification-declaration/Chip-Test-CD-Signing-Cert.pem -K |
| 156 | + // credentials/test/certification-declaration/Chip-Test-CD-Signing-Key.pem --out cd.bin -f 1 -V 6006 -p B002 -d 000E -c |
| 157 | + // "ZIG0000000000000000" -l 0 -i 0 -n 0001 -t 0 |
| 158 | + const uint8_t kCdContents[] = { |
| 159 | + 0x30, 0x3c, 0x38, 0x31, 0x3e, 0xe7, 0x5e, 0x46, 0x20, 0x20, 0x2a, 0x3c, 0x38, 0x36, 0x3e, 0x48, 0x3c, 0x38, 0x36, 0x3e, |
| 160 | + 0xf7, 0x5e, 0x4d, 0x5e, 0x41, 0x5e, 0x47, 0x5e, 0x42, 0xa0, 0x3c, 0x38, 0x31, 0x3e, 0xd9, 0x30, 0x3c, 0x38, 0x31, 0x3e, |
| 161 | + 0xd6, 0x5e, 0x42, 0x5e, 0x41, 0x5e, 0x43, 0x31, 0x5e, 0x4d, 0x30, 0x5e, 0x4b, 0x5e, 0x46, 0x20, 0x60, 0x3c, 0x38, 0x36, |
| 162 | + 0x3e, 0x48, 0x5e, 0x41, 0x65, 0x5e, 0x43, 0x5e, 0x44, 0x5e, 0x42, 0x5e, 0x41, 0x30, 0x43, 0x5e, 0x46, 0x20, 0x2a, 0x3c, |
| 163 | + 0x38, 0x36, 0x3e, 0x48, 0x3c, 0x38, 0x36, 0x3e, 0xf7, 0x5e, 0x4d, 0x5e, 0x41, 0x5e, 0x47, 0x5e, 0x41, 0xa0, 0x36, 0x5e, |
| 164 | + 0x44, 0x34, 0x5e, 0x55, 0x24, 0x5e, 0x40, 0x5e, 0x41, 0x25, 0x5e, 0x41, 0x5e, 0x46, 0x60, 0x36, 0x5e, 0x42, 0x5e, 0x45, |
| 165 | + 0x5e, 0x42, 0xb0, 0x5e, 0x58, 0x24, 0x5e, 0x43, 0x5e, 0x4e, 0x2c, 0x5e, 0x44, 0x5e, 0x53, 0x5a, 0x49, 0x47, 0x30, 0x30, |
| 166 | + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x24, 0x5e, 0x45, 0x5e, 0x40, 0x24, |
| 167 | + 0x5e, 0x46, 0x5e, 0x40, 0x24, 0x5e, 0x47, 0x5e, 0x41, 0x24, 0x5e, 0x48, 0x5e, 0x40, 0x5e, 0x58, 0x31, 0x7d, 0x30, 0x7b, |
| 168 | + 0x5e, 0x42, 0x5e, 0x41, 0x5e, 0x43, 0x3c, 0x38, 0x30, 0x3e, 0x5e, 0x54, 0x62, 0xfa, 0x3c, 0x38, 0x32, 0x3e, 0x33, 0x59, |
| 169 | + 0xac, 0xfa, 0xa9, 0x3c, 0x39, 0x36, 0x3e, 0x3e, 0x5e, 0x5c, 0xfa, 0x5e, 0x54, 0x0a, 0xdd, 0xf5, 0x5e, 0x44, 0xf3, 0x71, |
| 170 | + 0x60, 0x30, 0x5e, 0x4b, 0x5e, 0x46, 0x20, 0x20, 0x60, 0x3c, 0x38, 0x36, 0x3e, 0x48, 0x5e, 0x41, 0x65, 0x5e, 0x43, 0x5e, |
| 171 | + 0x44, 0x5e, 0x42, 0x5e, 0x41, 0x30, 0x0a, 0x5e, 0x46, 0x5e, 0x48, 0x2a, 0x3c, 0x38, 0x36, 0x3e, 0x48, 0xce, 0x3d, 0x5e, |
| 172 | + 0x44, 0x5e, 0x43, 0x5e, 0x42, 0x5e, 0x44, 0x47, 0x30, 0x45, 0x5e, 0x42, 0x21, 0x5e, 0x40, 0xa9, 0x5e, 0x51, 0x5e, 0x41, |
| 173 | + 0x5e, 0x45, 0x3c, 0x39, 0x38, 0x3e, 0x47, 0x3c, 0x38, 0x38, 0x3e, 0xcf, 0xd3, 0x29, 0xbf, 0xdf, 0x2e, 0x61, 0xb1, 0x3c, |
| 174 | + 0x38, 0x30, 0x3e, 0xca, 0xdd, 0x3c, 0x38, 0x33, 0x3e, 0x5c, 0xb6, 0xbb, 0x43, 0x3c, 0x39, 0x34, 0x3e, 0x3c, 0x39, 0x37, |
| 175 | + 0x3e, 0x45, 0x36, 0xe3, 0x30, 0x5c, 0x67, 0xf6, 0x5e, 0x42, 0x20, 0x36, 0x3c, 0x38, 0x61, 0x3e, 0x3c, 0x39, 0x33, 0x3e, |
| 176 | + 0x51, 0x65, 0x5e, 0x59, 0x5e, 0x45, 0x3c, 0x38, 0x62, 0x3e, 0x5e, 0x5e, 0x7e, 0x5f, 0x5e, 0x44, 0x5e, 0x4d, 0x7e, 0x6a, |
| 177 | + 0x77, 0xc7, 0xd2, 0x5e, 0x43, 0xdf, 0xd7, 0x2e, 0x2b, 0x3c, 0x39, 0x66, 0x3e, 0xec, 0xed, 0x33, 0xc9, 0x31, 0x51, 0x5e, |
| 178 | + 0x4c, 0xa7 |
| 179 | + }; |
| 180 | + return chip::CopySpanToMutableSpan(chip::ByteSpan{ kCdContents }, out_cd_buffer); |
| 181 | + } |
| 182 | + |
| 183 | + CHIP_ERROR GetFirmwareInformation(chip::MutableByteSpan & out_firmware_info_buffer) override |
| 184 | + { |
| 185 | + out_firmware_info_buffer.reduce_size(0); |
| 186 | + return CHIP_NO_ERROR; |
| 187 | + } |
| 188 | + CHIP_ERROR GetDeviceAttestationCert(chip::MutableByteSpan & out_dac_buffer) override |
| 189 | + { |
| 190 | + return chip::CopySpanToMutableSpan(chip::ByteSpan(kDevelopmentDAC_Cert_6006_B002), out_dac_buffer); |
| 191 | + } |
| 192 | + CHIP_ERROR GetProductAttestationIntermediateCert(chip::MutableByteSpan & out_pai_buffer) override |
| 193 | + { |
| 194 | + return chip::CopySpanToMutableSpan(chip::ByteSpan(kDevelopmentPAI_Cert_6006), out_pai_buffer); |
| 195 | + } |
| 196 | + CHIP_ERROR SignWithDeviceAttestationKey(const chip::ByteSpan & message_to_sign, |
| 197 | + chip::MutableByteSpan & out_signature_buffer) override |
| 198 | + { |
| 199 | + chip::Crypto::P256ECDSASignature signature; |
| 200 | + chip::Crypto::P256Keypair keypair; |
| 201 | + |
| 202 | + VerifyOrReturnError(!out_signature_buffer.empty(), CHIP_ERROR_INVALID_ARGUMENT); |
| 203 | + VerifyOrReturnError(!message_to_sign.empty(), CHIP_ERROR_INVALID_ARGUMENT); |
| 204 | + VerifyOrReturnError(out_signature_buffer.size() >= signature.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL); |
| 205 | + |
| 206 | + // In a non-exemplary implementation, the public key is not needed here. It is used here merely because |
| 207 | + // Crypto::P256Keypair is only (currently) constructable from raw keys if both private/public keys are present. |
| 208 | + chip::ByteSpan sk_span{ kDevelopmentDAC_PrivateKey_6006_B002 }; |
| 209 | + |
| 210 | + chip::ByteSpan pk_span{ kDevelopmentDAC_PublicKey_6006_B002 }; |
| 211 | + |
| 212 | + ReturnErrorOnFailure(LoadKeypairFromRaw(sk_span, pk_span, keypair)); |
| 213 | + ReturnErrorOnFailure(keypair.ECDSA_sign_msg(message_to_sign.data(), message_to_sign.size(), signature)); |
| 214 | + |
| 215 | + return chip::CopySpanToMutableSpan(chip::ByteSpan{ signature.ConstBytes(), signature.Length() }, out_signature_buffer); |
| 216 | + } |
| 217 | + |
| 218 | +private: |
| 219 | + CHIP_ERROR LoadKeypairFromRaw(chip::ByteSpan private_key, chip::ByteSpan public_key, chip::Crypto::P256Keypair & keypair) |
| 220 | + { |
| 221 | + chip::Crypto::P256SerializedKeypair serialized_keypair; |
| 222 | + ReturnErrorOnFailure(serialized_keypair.SetLength(private_key.size() + public_key.size())); |
| 223 | + memcpy(serialized_keypair.Bytes(), public_key.data(), public_key.size()); |
| 224 | + memcpy(serialized_keypair.Bytes() + public_key.size(), private_key.data(), private_key.size()); |
| 225 | + return keypair.Deserialize(serialized_keypair); |
| 226 | + } |
| 227 | +}; |
| 228 | + |
| 229 | +class DrinkMachineMatterProviders |
| 230 | +{ |
| 231 | +public: |
| 232 | + DrinkMachineMatterProviders() {} |
| 233 | + ~DrinkMachineMatterProviders() {} |
| 234 | + |
| 235 | + DrinkMachineMatterProviders(const DrinkMachineMatterProviders &) = delete; |
| 236 | + DrinkMachineMatterProviders & operator=(const DrinkMachineMatterProviders &) = delete; |
| 237 | + |
| 238 | + void Init() |
| 239 | + { |
| 240 | + chip::Credentials::SetDeviceAttestationCredentialsProvider(&mCreds); |
| 241 | + mInfo.Register(); |
| 242 | + } |
| 243 | + |
| 244 | + static DrinkMachineMatterProviders & GetInstance() |
| 245 | + { |
| 246 | + static DrinkMachineMatterProviders instance; |
| 247 | + return instance; |
| 248 | + } |
| 249 | + |
| 250 | +private: |
| 251 | + DrinkMachineCredentialsProvider mCreds; |
| 252 | + DrinkMachineInfoProvider mInfo; |
| 253 | +}; |
| 254 | + |
| 255 | +} // namespace matter |
| 256 | +} // namespace google |
0 commit comments