Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 52f0c17

Browse files
committed
Added Operational Device Credentials Generation Function for the Weave Device Layer.
-- If needed, this function is called early during Weave stack initialization to provision device with initial set of operational credentials. -- In a special case, when device doesn't have operational credentials but it is already paired to account, a flag will be set that manufacturer-assigned credentials should be used as operational credentials.
1 parent 715fa56 commit 52f0c17

File tree

6 files changed

+202
-30
lines changed

6 files changed

+202
-30
lines changed

src/adaptations/device-layer/DeviceControlServer.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,15 @@ WEAVE_ERROR DeviceControlServer::OnResetConfig(uint16_t resetFlags)
118118
}
119119

120120
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
121-
// If the device operational credentials reset has been requested, clear
122-
// the device operational credentials, if present.
121+
// If the operational device credentials reset has been requested, clear
122+
// and generate new operational device certificate and private key.
123123
if ((resetFlags & kResetConfigFlag_OperationalCredentials) != 0)
124124
{
125-
WeaveLogProgress(DeviceLayer, "Reset operational credentials");
126-
tmpErr = ConfigurationMgr().ClearOperationalDeviceCredentials();
125+
WeaveLogProgress(DeviceLayer, "Reset operational device certificate and private key");
126+
tmpErr = ConfigurationMgr().GenerateAndStoreOperationalDeviceCertAndPrivateKey();
127127
if (tmpErr != WEAVE_NO_ERROR)
128128
{
129-
WeaveLogProgress(DeviceLayer, "ConfigurationMgr().ClearOperationalDeviceCredentials() failed: %s", ErrorStr(tmpErr));
129+
WeaveLogProgress(DeviceLayer, "ConfigurationMgr().GenerateAndStoreOperationalDeviceCertAndPrivateKey() failed: %s", ErrorStr(tmpErr));
130130
err = (err == WEAVE_NO_ERROR) ? tmpErr : err;
131131
}
132132
}

src/adaptations/device-layer/include/Weave/DeviceLayer/ConfigurationManager.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ class ConfigurationManager
125125
bool IsMemberOfFabric();
126126
bool IsFullyProvisioned();
127127
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
128-
bool OperationalDeviceCredentialsProvisioned();
128+
bool OperationalDeviceIdProvisioned(void);
129+
bool OperationalDeviceCertAndPrivateKeyProvisioned(void);
129130
#endif
130131

131132
void InitiateFactoryReset();
@@ -155,7 +156,8 @@ class ConfigurationManager
155156
WEAVE_ERROR ReadPersistedStorageValue(::nl::Weave::Platform::PersistedStorage::Key key, uint32_t & value);
156157
WEAVE_ERROR WritePersistedStorageValue(::nl::Weave::Platform::PersistedStorage::Key key, uint32_t value);
157158
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
158-
WEAVE_ERROR ClearOperationalDeviceCredentials(void);
159+
WEAVE_ERROR GenerateAndStoreOperationalDeviceId(void);
160+
WEAVE_ERROR GenerateAndStoreOperationalDeviceCertAndPrivateKey(void);
159161
void UseManufacturerCredentialsAsOperational(bool val);
160162
#endif
161163

@@ -521,14 +523,24 @@ inline WEAVE_ERROR ConfigurationManager::SetFailSafeArmed(bool val)
521523

522524
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
523525

524-
inline bool ConfigurationManager::OperationalDeviceCredentialsProvisioned()
526+
inline bool ConfigurationManager::OperationalDeviceIdProvisioned()
525527
{
526-
return static_cast<ImplClass*>(this)->_OperationalDeviceCredentialsProvisioned();
528+
return static_cast<ImplClass*>(this)->_OperationalDeviceIdProvisioned();
527529
}
528530

529-
inline WEAVE_ERROR ConfigurationManager::ClearOperationalDeviceCredentials(void)
531+
inline bool ConfigurationManager::OperationalDeviceCertAndPrivateKeyProvisioned()
530532
{
531-
return static_cast<ImplClass*>(this)->_ClearOperationalDeviceCredentials();
533+
return static_cast<ImplClass*>(this)->_OperationalDeviceCertAndPrivateKeyProvisioned();
534+
}
535+
536+
inline WEAVE_ERROR ConfigurationManager::GenerateAndStoreOperationalDeviceId(void)
537+
{
538+
return static_cast<ImplClass*>(this)->_GenerateAndStoreOperationalDeviceId();
539+
}
540+
541+
inline WEAVE_ERROR ConfigurationManager::GenerateAndStoreOperationalDeviceCertAndPrivateKey(void)
542+
{
543+
return static_cast<ImplClass*>(this)->_GenerateAndStoreOperationalDeviceCertAndPrivateKey();
532544
}
533545

534546
inline void ConfigurationManager::UseManufacturerCredentialsAsOperational(bool val)

src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ class GenericConfigurationManagerImpl
7575
WEAVE_ERROR _StoreDeviceCertificate(const uint8_t * cert, size_t certLen);
7676
WEAVE_ERROR _StoreDeviceIntermediateCACerts(const uint8_t * certs, size_t certsLen);
7777
WEAVE_ERROR _StoreDevicePrivateKey(const uint8_t * key, size_t keyLen);
78-
WEAVE_ERROR _ClearOperationalDeviceCredentials(void);
7978
#endif
8079
WEAVE_ERROR _GetManufacturerDeviceId(uint64_t & deviceId);
8180
WEAVE_ERROR _StoreManufacturerDeviceId(uint64_t deviceId);
@@ -110,7 +109,10 @@ class GenericConfigurationManagerImpl
110109
bool _IsFullyProvisioned();
111110
WEAVE_ERROR _ComputeProvisioningHash(uint8_t * hashBuf, size_t hashBufSize);
112111
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
113-
bool _OperationalDeviceCredentialsProvisioned();
112+
WEAVE_ERROR _GenerateAndStoreOperationalDeviceId(void);
113+
WEAVE_ERROR _GenerateAndStoreOperationalDeviceCertAndPrivateKey(void);
114+
bool _OperationalDeviceIdProvisioned(void);
115+
bool _OperationalDeviceCertAndPrivateKeyProvisioned(void);
114116
void _UseManufacturerCredentialsAsOperational(bool val);
115117
#endif
116118

@@ -121,8 +123,7 @@ class GenericConfigurationManagerImpl
121123
kFlag_IsServiceProvisioned = 0x01,
122124
kFlag_IsMemberOfFabric = 0x02,
123125
kFlag_IsPairedToAccount = 0x04,
124-
kFlag_OperationalDeviceCredentialsProvisioned = 0x08,
125-
kFlag_UseManufacturerCredentialsAsOperational = 0x10,
126+
kFlag_UseManufacturerCredentialsAsOperational = 0x08,
126127
};
127128

128129
uint8_t mFlags;

src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp

Lines changed: 141 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h>
3131
#include <BleLayer/WeaveBleServiceData.h>
3232
#include <Weave/Support/Base64.h>
33+
#include <Weave/Profiles/security/WeavePrivateKey.h>
3334

3435
#if WEAVE_DEVICE_CONFIG_ENABLE_THREAD
3536
#include <Weave/DeviceLayer/ThreadStackManager.h>
@@ -53,7 +54,6 @@ WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_Init()
5354
SetFlag(mFlags, kFlag_IsServiceProvisioned, Impl()->ConfigValueExists(ImplClass::kConfigKey_ServiceConfig));
5455
SetFlag(mFlags, kFlag_IsMemberOfFabric, Impl()->ConfigValueExists(ImplClass::kConfigKey_FabricId));
5556
SetFlag(mFlags, kFlag_IsPairedToAccount, Impl()->ConfigValueExists(ImplClass::kConfigKey_PairedAccountId));
56-
SetFlag(mFlags, kFlag_OperationalDeviceCredentialsProvisioned, Impl()->ConfigValueExists(ImplClass::kConfigKey_OperationalDeviceCert));
5757

5858
return WEAVE_NO_ERROR;
5959
}
@@ -502,26 +502,19 @@ WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDevicePrivateKey(c
502502
}
503503

504504
template<class ImplClass>
505-
WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearOperationalDeviceCredentials(void)
505+
bool GenericConfigurationManagerImpl<ImplClass>::_OperationalDeviceIdProvisioned(void)
506506
{
507-
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceId);
508-
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceCert);
509-
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceICACerts);
510-
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDevicePrivateKey);
511-
512-
ClearFlag(mFlags, kFlag_OperationalDeviceCredentialsProvisioned);
513-
514-
return WEAVE_NO_ERROR;
507+
return Impl()->ConfigValueExists(ImplClass::kConfigKey_OperationalDeviceId);
515508
}
516509

517510
template<class ImplClass>
518-
bool GenericConfigurationManagerImpl<ImplClass>::_OperationalDeviceCredentialsProvisioned()
511+
bool GenericConfigurationManagerImpl<ImplClass>::_OperationalDeviceCertAndPrivateKeyProvisioned(void)
519512
{
520-
return ::nl::GetFlag(mFlags, kFlag_OperationalDeviceCredentialsProvisioned);
513+
return Impl()->ConfigValueExists(ImplClass::kConfigKey_OperationalDeviceCert);
521514
}
522515

523516
template<class ImplClass>
524-
bool GenericConfigurationManagerImpl<ImplClass>::UseManufacturerCredentialsAsOperational()
517+
bool GenericConfigurationManagerImpl<ImplClass>::UseManufacturerCredentialsAsOperational(void)
525518
{
526519
return ::nl::GetFlag(mFlags, kFlag_UseManufacturerCredentialsAsOperational);
527520
}
@@ -532,6 +525,132 @@ void GenericConfigurationManagerImpl<ImplClass>::_UseManufacturerCredentialsAsOp
532525
SetFlag(mFlags, kFlag_UseManufacturerCredentialsAsOperational, val);
533526
}
534527

528+
static WEAVE_ERROR GenerateOperationalECDSASignature(const uint8_t *hash, uint8_t hashLen, EncodedECDSASignature& ecdsaSig)
529+
{
530+
WEAVE_ERROR err;
531+
uint8_t * weavePrivKey = NULL;
532+
size_t weavePrivKeyLen;
533+
uint32_t weaveCurveId;
534+
EncodedECPublicKey pubKey;
535+
EncodedECPrivateKey privKey;
536+
537+
// Determine the length of the private key.
538+
err = ConfigurationMgr().GetDevicePrivateKey((uint8_t *)NULL, 0, weavePrivKeyLen);
539+
SuccessOrExit(err);
540+
541+
// Fail if no private key has been configured.
542+
VerifyOrExit(weavePrivKeyLen != 0, err = WEAVE_ERROR_KEY_NOT_FOUND);
543+
544+
// Create a temporary buffer to hold the private key.
545+
weavePrivKey = (uint8_t *)Platform::Security::MemoryAlloc(weavePrivKeyLen);
546+
VerifyOrExit(weavePrivKey != NULL, err = WEAVE_ERROR_NO_MEMORY);
547+
548+
// Read the private key.
549+
err = ConfigurationMgr().GetDevicePrivateKey(weavePrivKey, weavePrivKeyLen, weavePrivKeyLen);
550+
SuccessOrExit(err);
551+
552+
// Decode operational device private/public keys from private key TLV structure.
553+
err = Profiles::Security::DecodeWeaveECPrivateKey(weavePrivKey, weavePrivKeyLen, weaveCurveId, pubKey, privKey);
554+
SuccessOrExit(err);
555+
556+
// Generate operational device signature.
557+
err = nl::Weave::Crypto::GenerateECDSASignature(Profiles::Security::WeaveCurveIdToOID(weaveCurveId),
558+
hash, hashLen, privKey, ecdsaSig);
559+
SuccessOrExit(err);
560+
561+
exit:
562+
if (weavePrivKey != NULL)
563+
{
564+
Platform::Security::MemoryFree(weavePrivKey);
565+
}
566+
return err;
567+
}
568+
569+
template<class ImplClass>
570+
WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GenerateAndStoreOperationalDeviceId(void)
571+
{
572+
WEAVE_ERROR err;
573+
uint64_t deviceId;
574+
575+
// Generate random device Id.
576+
err = GenerateWeaveNodeId(deviceId);
577+
SuccessOrExit(err);
578+
579+
// Store generated device Id.
580+
err = _StoreDeviceId(deviceId);
581+
SuccessOrExit(err);
582+
583+
exit:
584+
if (err != WEAVE_NO_ERROR)
585+
{
586+
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceId);
587+
}
588+
return err;
589+
}
590+
591+
template<class ImplClass>
592+
WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GenerateAndStoreOperationalDeviceCertAndPrivateKey(void)
593+
{
594+
enum
595+
{
596+
kWeaveDeviceCertBufSize = 300, // Size of buffer needed to hold Weave device certificate.
597+
kWeaveDevicePrivateKeyBufSize = 128, // Size of buffer needed to hold Weave device private key.
598+
};
599+
600+
WEAVE_ERROR err;
601+
uint64_t deviceId;
602+
uint8_t weavePrivKey[kWeaveDevicePrivateKeyBufSize];
603+
uint32_t weavePrivKeyLen;
604+
uint8_t weaveCert[kWeaveDeviceCertBufSize];
605+
uint16_t weaveCertLen;
606+
uint8_t privKeyBuf[EncodedECPrivateKey::kMaxValueLength];
607+
uint8_t pubKeyBuf[EncodedECPublicKey::kMaxValueLength];
608+
EncodedECPublicKey pubKey;
609+
EncodedECPrivateKey privKey;
610+
611+
// Clear intermediate CA certificate if it was provisioned.
612+
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceICACerts);
613+
614+
// Get operational device Id.
615+
err = _GetDeviceId(deviceId);
616+
SuccessOrExit(err);
617+
618+
privKey.PrivKey = privKeyBuf;
619+
privKey.PrivKeyLen = sizeof(privKeyBuf);
620+
621+
pubKey.ECPoint = pubKeyBuf;
622+
pubKey.ECPointLen = sizeof(pubKeyBuf);
623+
624+
// Generate random EC private/public key pair.
625+
err = GenerateECDHKey(Profiles::Security::WeaveCurveIdToOID(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID), pubKey, privKey);
626+
SuccessOrExit(err);
627+
628+
// Encode Weave device EC private/public key pair into EllipticCurvePrivateKey TLV structure.
629+
err = EncodeWeaveECPrivateKey(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID, &pubKey, privKey,
630+
weavePrivKey, sizeof(weavePrivKey), weavePrivKeyLen);
631+
SuccessOrExit(err);
632+
633+
// Store generated operational device private key.
634+
err = _StoreDevicePrivateKey(weavePrivKey, weavePrivKeyLen);
635+
SuccessOrExit(err);
636+
637+
// Generate self-signed operational device certificate.
638+
err = Profiles::Security::GenerateOperationalDeviceCert(deviceId, pubKey, weaveCert, sizeof(weaveCert), weaveCertLen, GenerateOperationalECDSASignature);
639+
SuccessOrExit(err);
640+
641+
// Store generated operational device certificate.
642+
err = _StoreDeviceCertificate(weaveCert, weaveCertLen);
643+
SuccessOrExit(err);
644+
645+
exit:
646+
if (err != WEAVE_NO_ERROR)
647+
{
648+
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceCert);
649+
Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDevicePrivateKey);
650+
}
651+
return err;
652+
}
653+
535654
#endif // WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
536655

537656
template<class ImplClass>
@@ -666,6 +785,14 @@ WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearServiceProvisionin
666785
Impl()->ClearConfigValue(ImplClass::kConfigKey_ServiceConfig);
667786
Impl()->ClearConfigValue(ImplClass::kConfigKey_PairedAccountId);
668787

788+
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
789+
// If necessary, generate new operational device credentials (certificate and private key).
790+
if (_IsPairedToAccount() || _IsServiceProvisioned())
791+
{
792+
_GenerateAndStoreOperationalDeviceCertAndPrivateKey();
793+
}
794+
#endif
795+
669796
// TODO: Move these behaviors out of configuration manager.
670797

671798
// If necessary, post an event alerting other subsystems to the change in
@@ -899,7 +1026,7 @@ bool GenericConfigurationManagerImpl<ImplClass>::_IsFullyProvisioned()
8991026
Impl()->IsPairedToAccount() &&
9001027
#endif
9011028
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
902-
(!UseManufacturerCredentialsAsOperational() && _OperationalDeviceCredentialsProvisioned()) &&
1029+
(!UseManufacturerCredentialsAsOperational() && _OperationalDeviceCertAndPrivateKeyProvisioned()) &&
9031030
#endif
9041031
Impl()->IsMemberOfFabric();
9051032
}

src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericPlatformManagerImpl.ipp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
*
3+
* Copyright (c) 2020 Google LLC.
34
* Copyright (c) 2018 Nest Labs, Inc.
45
* All rights reserved.
56
*
@@ -82,6 +83,37 @@ WEAVE_ERROR GenericPlatformManagerImpl<ImplClass>::_InitWeaveStack(void)
8283
}
8384
SuccessOrExit(err);
8485

86+
#if WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
87+
if (!ConfigurationMgr().OperationalDeviceCertAndPrivateKeyProvisioned())
88+
{
89+
// If paired to account keep using manufacturer device credentials as operational.
90+
if (ConfigurationMgr().IsServiceProvisioned() && ConfigurationMgr().IsPairedToAccount())
91+
{
92+
ConfigurationMgr().UseManufacturerCredentialsAsOperational(true);
93+
}
94+
// Otherwise, generate and store operational device credentials.
95+
else
96+
{
97+
if (!ConfigurationMgr().OperationalDeviceIdProvisioned())
98+
{
99+
err = ConfigurationMgr().GenerateAndStoreOperationalDeviceId();
100+
}
101+
if (err != WEAVE_NO_ERROR)
102+
{
103+
WeaveLogError(DeviceLayer, "GenerateAndStoreOperationalDeviceId() failed: %s", ErrorStr(err));
104+
}
105+
SuccessOrExit(err);
106+
107+
err = ConfigurationMgr().GenerateAndStoreOperationalDeviceCertAndPrivateKey();
108+
if (err != WEAVE_NO_ERROR)
109+
{
110+
WeaveLogError(DeviceLayer, "GenerateAndStoreOperationalDeviceCertAndPrivateKey() failed: %s", ErrorStr(err));
111+
}
112+
SuccessOrExit(err);
113+
}
114+
}
115+
#endif // WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING
116+
85117
// Initialize the Weave Inet layer.
86118
new (&InetLayer) Inet::InetLayer();
87119
err = InetLayer.Init(SystemLayer, NULL);

src/lib/profiles/device-control/DeviceControl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ enum
111111
kResetConfigFlag_NetworkConfig = 0x0001, /**< Reset network configuration information. */
112112
kResetConfigFlag_FabricConfig = 0x0002, /**< Reset fabric configuration information. */
113113
kResetConfigFlag_ServiceConfig = 0x0004, /**< Reset network configuration information. */
114-
kResetConfigFlag_OperationalCredentials = 0x0008, /**< Reset device operational credentials. */
114+
kResetConfigFlag_OperationalCredentials = 0x4000, /**< Reset device operational credentials. */
115115
kResetConfigFlag_FactoryDefaults = 0x8000 /**< Reset device to full factory defaults. */
116116
};
117117

0 commit comments

Comments
 (0)