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
504504template <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
517510template <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
523516template <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
537656template <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}
0 commit comments