WIP: Support Certificate Provisioning at the Weave Device Layer.
diff --git a/src/adaptations/device-layer/CASEAuth.cpp b/src/adaptations/device-layer/CASEAuth.cpp
index e23b6de..8aab685 100644
--- a/src/adaptations/device-layer/CASEAuth.cpp
+++ b/src/adaptations/device-layer/CASEAuth.cpp
@@ -147,7 +147,7 @@
SuccessOrExit(err);
// Fail if no private key has been configured.
- VerifyOrExit(privKeyLen != 0, err = WEAVE_ERROR_CERT_NOT_FOUND);
+ VerifyOrExit(privKeyLen != 0, err = WEAVE_ERROR_KEY_NOT_FOUND);
// Create a temporary buffer to hold the private key.
mPrivKeyBuf = (uint8_t *)MemoryAlloc(privKeyLen);
diff --git a/src/adaptations/device-layer/CertificateProvisioningClient.cpp b/src/adaptations/device-layer/CertificateProvisioningClient.cpp
new file mode 100644
index 0000000..ad6ee2e
--- /dev/null
+++ b/src/adaptations/device-layer/CertificateProvisioningClient.cpp
@@ -0,0 +1,602 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
+#include <Weave/DeviceLayer/internal/CertificateProvisioningClient.h>
+#include <Weave/Core/WeaveTLV.h>
+#include <Weave/Profiles/common/CommonProfile.h>
+#include <Weave/Profiles/security/WeaveCert.h>
+#include <Weave/Profiles/security/WeavePrivateKey.h>
+#include <Weave/Profiles/security/WeaveSig.h>
+
+using namespace ::nl;
+using namespace ::nl::Weave;
+using namespace ::nl::Weave::TLV;
+using namespace ::nl::Weave::Profiles;
+using namespace ::nl::Weave::Profiles::Security;
+using namespace ::nl::Weave::Profiles::Security::CertProvisioning;
+using namespace ::nl::Weave::Platform::Security;
+
+namespace nl {
+namespace Weave {
+namespace DeviceLayer {
+namespace Internal {
+
+using ::nl::Weave::Platform::Security::MemoryAlloc;
+using ::nl::Weave::Platform::Security::MemoryFree;
+
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+
+static EncodedECPrivateKey sDevicePrivKey;
+
+static WEAVE_ERROR sGenerateDeviceECDSASignature(const uint8_t *hash, uint8_t hashLen, EncodedECDSASignature& ecdsaSig)
+{
+ return nl::Weave::Crypto::GenerateECDSASignature(WeaveCurveIdToOID(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID),
+ hash, hashLen, sDevicePrivKey, ecdsaSig);
+}
+
+/**
+ * Generates and stores Weave operational device credentials:
+ * -- Weave device Id (if needed)
+ * -- Weave device self-signed certificate
+ * -- Weave device private key
+ *
+ * @retval #WEAVE_NO_ERROR If Weave device credentials were successfully generated and stored.
+ */
+WEAVE_ERROR GenerateAndStoreOperationalDeviceCredentials(uint64_t deviceId)
+{
+ enum {
+ kWeaveDeviceKeyBufSize = 128,
+ kWeaveDeviceCertBufSize = 300,
+ };
+ WEAVE_ERROR err;
+ uint8_t key[kWeaveDeviceKeyBufSize];
+ uint32_t keyLen;
+ uint8_t cert[kWeaveDeviceCertBufSize];
+ uint16_t certLen;
+ uint8_t privKey[EncodedECPrivateKey::kMaxValueLength];
+ uint8_t pubKey[EncodedECPublicKey::kMaxValueLength];
+ EncodedECPublicKey devicePubKey;
+
+ // If not specified, generate random device Id.
+ if (deviceId == kNodeIdNotSpecified)
+ {
+ err = GenerateWeaveNodeId(deviceId);
+ SuccessOrExit(err);
+ }
+
+ sDevicePrivKey.PrivKey = privKey;
+ sDevicePrivKey.PrivKeyLen = sizeof(privKey);
+
+ devicePubKey.ECPoint = pubKey;
+ devicePubKey.ECPointLen = sizeof(pubKey);
+
+ // Generate random EC private/public key pair.
+ err = GenerateECDHKey(WeaveCurveIdToOID(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID), devicePubKey, sDevicePrivKey);
+ SuccessOrExit(err);
+
+ // Encode Weave device EC private/public key pair into EllipticCurvePrivateKey TLV structure.
+ err = EncodeWeaveECPrivateKey(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID, &devicePubKey, sDevicePrivKey, key, sizeof(key), keyLen);
+ SuccessOrExit(err);
+
+ // Generate self-signed operational device certificate.
+ err = GenerateOperationalDeviceCert(deviceId, devicePubKey, cert, sizeof(cert), certLen, sGenerateDeviceECDSASignature);
+ SuccessOrExit(err);
+
+ // Store generated device credentials.
+ err = ConfigurationMgr().StoreDeviceCredentials(deviceId, cert, certLen, key, keyLen);
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+WEAVE_ERROR CertificateProvisioningClient::Init(uint8_t reqType)
+{
+ return Init(reqType, NULL);
+}
+
+/**
+ * Initialize certificate provisioning client.
+ *
+ * @param[in] reqType Get certificate request type.
+ * @param[in] encodeReqAuthInfo A pointer to a function that generates ECDSA signature on the given
+ * certificate hash using operational device private key.
+ *
+ * @retval #WEAVE_NO_ERROR If certificate provisioning client was successfully initialized.
+ */
+WEAVE_ERROR CertificateProvisioningClient::Init(uint8_t reqType, EncodeReqAuthInfoFunct encodeReqAuthInfo)
+{
+ mReqType = reqType;
+ mDoManufAttest = (reqType == WeaveCertProvEngine::kReqType_GetInitialOpDeviceCert) ? true : false;
+
+ mEncodeReqAuthInfo = encodeReqAuthInfo;
+
+ mBinding = NULL;
+ mWaitingForServiceConnectivity = false;
+
+ return WEAVE_NO_ERROR;
+}
+
+/**
+ * Handler for Certificate Provisioning Client API events.
+ *
+ * @param[in] appState A pointer to application-defined state information associated with the client object.
+ * @param[in] eventType Event ID passed by the event callback.
+ * @param[in] inParam Reference of input event parameters passed by the event callback.
+ * @param[in] outParam Reference of output event parameters passed by the event callback.
+ *
+ */
+void CertificateProvisioningClient::CertProvClientEventHandler(void * appState, WeaveCertProvEngine::EventType eventType, const WeaveCertProvEngine::InEventParam & inParam, WeaveCertProvEngine::OutEventParam & outParam)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ CertificateProvisioningClient * client = static_cast<CertificateProvisioningClient *>(appState);
+ WeaveCertProvEngine * certProvEngine = inParam.Source;
+
+ switch (eventType)
+ {
+ case WeaveCertProvEngine::kEvent_PrepareAuthorizeInfo:
+ {
+ if (client->mEncodeReqAuthInfo != NULL)
+ {
+ WeaveLogProgress(DeviceLayer, "Preparing authorization information for the GetCertificateRequest message");
+
+ err = client->mEncodeReqAuthInfo(*inParam.PrepareAuthorizeInfo.Writer);
+ SuccessOrExit(err);
+ }
+
+ break;
+ }
+
+ case WeaveCertProvEngine::kEvent_ResponseReceived:
+ {
+ if (inParam.ResponseReceived.ReplaceCert)
+ {
+ // Store service issued operational device certificate.
+ err = ConfigurationMgr().StoreDeviceCertificate(inParam.ResponseReceived.Cert, inParam.ResponseReceived.CertLen);
+ SuccessOrExit(err);
+
+ if (inParam.ResponseReceived.RelatedCerts != NULL)
+ {
+ // Store device intermediate CA certificates related to the service issued operational device certificate.
+ err = ConfigurationMgr().StoreDeviceICACerts(inParam.ResponseReceived.RelatedCerts, inParam.ResponseReceived.RelatedCertsLen);
+ SuccessOrExit(err);
+ }
+
+ // Post an event alerting other subsystems that the device now has new certificate.
+ {
+ WeaveDeviceEvent event;
+ event.Type = DeviceEventType::kDeviceCredentialsChange;
+ event.DeviceCredentialsChange.AreCredentialsProvisioned = true;
+ PlatformMgr().PostEvent(&event);
+ }
+
+ WeaveLogProgress(DeviceLayer, "Stored new operational device certificate received from the CA service");
+ }
+ else
+ {
+ WeaveLogProgress(DeviceLayer, "CA service reported: no need to replace operational device certificate");
+ }
+
+ certProvEngine->AbortCertificateProvisioning();
+
+ break;
+ }
+
+ case WeaveCertProvEngine::kEvent_CommunicationError:
+ {
+ if (inParam.CommunicationError.Reason == WEAVE_ERROR_STATUS_REPORT_RECEIVED)
+ {
+ WeaveLogError(DeviceLayer, "Received status report from the CA service: %s",
+ nl::StatusReportStr(inParam.CommunicationError.RcvdStatusReport->mProfileId, inParam.CommunicationError.RcvdStatusReport->mStatusCode));
+ }
+ else
+ {
+ WeaveLogError(DeviceLayer, "Failed to prepare/send GetCertificateRequest message: %s", ErrorStr(inParam.CommunicationError.Reason));
+ }
+
+ certProvEngine->AbortCertificateProvisioning();
+
+ break;
+ }
+
+ default:
+ WeaveLogError(DeviceLayer, "Unrecognized certificate provisioning API event");
+ break;
+ }
+
+exit:
+ if (eventType == WeaveCertProvEngine::kEvent_PrepareAuthorizeInfo)
+ outParam.PrepareAuthorizeInfo.Error = err;
+ else if (eventType == WeaveCertProvEngine::kEvent_ResponseReceived)
+ outParam.ResponseReceived.Error = err;
+}
+
+// ===== Methods that implement the WeaveNodeOpAuthDelegate interface
+
+WEAVE_ERROR CertificateProvisioningClient::EncodeOpCert(TLVWriter & writer, uint64_t tag)
+{
+ WEAVE_ERROR err;
+ uint8_t * cert = NULL;
+ size_t certLen = 0;
+
+ // Determine the length of the operational device certificate.
+ err = ConfigurationMgr().GetDeviceCertificate((uint8_t *)NULL, 0, certLen);
+ SuccessOrExit(err);
+
+ // Fail if no operational device certificate has been configured.
+ VerifyOrExit(certLen != 0, err = WEAVE_ERROR_CERT_NOT_FOUND);
+
+ // Create a temporary buffer to hold the operational device certificate.
+ cert = static_cast<uint8_t *>(MemoryAlloc(certLen));
+ VerifyOrExit(cert != NULL, err = WEAVE_ERROR_NO_MEMORY);
+
+ // Read the operational device certificate.
+ err = ConfigurationMgr().GetDeviceCertificate(cert, certLen, certLen);
+ SuccessOrExit(err);
+
+ // Copy encoded operational device certificate.
+ err = writer.CopyContainer(tag, cert, certLen);
+ SuccessOrExit(err);
+
+exit:
+ if (cert != NULL)
+ {
+ MemoryFree(cert);
+ }
+ return err;
+}
+
+WEAVE_ERROR CertificateProvisioningClient::EncodeOpRelatedCerts(TLVWriter & writer, uint64_t tag)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ uint8_t * caCerts = NULL;
+ size_t caCertsLen = 0;
+
+ if (ConfigurationMgr().DeviceICACertsProvisioned())
+ {
+ // Determine the length of the operational device intermediate certificates.
+ err = ConfigurationMgr().GetDeviceICACerts((uint8_t *)NULL, 0, caCertsLen);
+ SuccessOrExit(err);
+
+ // Fail if no operational device intermediate certificates array has been configured.
+ VerifyOrExit(caCertsLen != 0, err = WEAVE_ERROR_CERT_NOT_FOUND);
+
+ // Create a temporary buffer to hold the operational device intermediate certificates.
+ caCerts = static_cast<uint8_t *>(MemoryAlloc(caCertsLen));
+ VerifyOrExit(caCerts != NULL, err = WEAVE_ERROR_NO_MEMORY);
+
+ // Read the operational device intermediate certificates.
+ err = ConfigurationMgr().GetDeviceCertificate(caCerts, caCertsLen, caCertsLen);
+ SuccessOrExit(err);
+
+ // Copy encoded operational device intermediate certificates array.
+ err = writer.CopyContainer(tag, caCerts, caCertsLen);
+ SuccessOrExit(err);
+ }
+
+exit:
+ if (caCerts != NULL)
+ {
+ MemoryFree(caCerts);
+ }
+ return err;
+}
+
+WEAVE_ERROR CertificateProvisioningClient::GenerateAndEncodeOpSig(const uint8_t * hash, uint8_t hashLen, TLVWriter & writer, uint64_t tag)
+{
+ WEAVE_ERROR err;
+ uint8_t * privKey = NULL;
+ size_t privKeyLen = 0;
+
+ // Determine the length of the operational device private key.
+ err = ConfigurationMgr().GetDevicePrivateKey((uint8_t *)NULL, 0, privKeyLen);
+ SuccessOrExit(err);
+
+ // Fail if no operational device private key has been configured.
+ VerifyOrExit(privKeyLen != 0, err = WEAVE_ERROR_KEY_NOT_FOUND);
+
+ // Create a temporary buffer to hold the operational device private key.
+ privKey = static_cast<uint8_t *>(MemoryAlloc(privKeyLen));
+ VerifyOrExit(privKey != NULL, err = WEAVE_ERROR_NO_MEMORY);
+
+ // Read the operational device private key.
+ err = ConfigurationMgr().GetDevicePrivateKey(privKey, privKeyLen, privKeyLen);
+ SuccessOrExit(err);
+
+ // Generate and encode operational device signature.
+ err = GenerateAndEncodeWeaveECDSASignature(writer, tag, hash, hashLen, privKey, privKeyLen);
+ SuccessOrExit(err);
+
+exit:
+ if (privKey != NULL)
+ {
+ MemoryFree(privKey);
+ }
+ return err;
+}
+
+// ===== Methods that implement the WeaveNodeManufAttestDelegate interface
+
+WEAVE_ERROR CertificateProvisioningClient::EncodeMAInfo(TLVWriter & writer)
+{
+ WEAVE_ERROR err;
+ uint8_t * cert = NULL;
+ size_t certLen = 0;
+
+ // Determine the length of the manufacturer attestation device certificate.
+ err = ConfigurationMgr().GetManufAttestDeviceCertificate((uint8_t *)NULL, 0, certLen);
+ SuccessOrExit(err);
+
+ // Fail if no manufacturer attestation device certificate has been configured.
+ VerifyOrExit(certLen != 0, err = WEAVE_ERROR_CERT_NOT_FOUND);
+
+ // Create a temporary buffer to hold the manufacturer attestation device certificate.
+ cert = static_cast<uint8_t *>(MemoryAlloc(certLen));
+ VerifyOrExit(cert != NULL, err = WEAVE_ERROR_NO_MEMORY);
+
+ // Read the manufacturer attestation device certificate.
+ err = ConfigurationMgr().GetManufAttestDeviceCertificate(cert, certLen, certLen);
+ SuccessOrExit(err);
+
+ // Copy encoded manufacturer attestation device certificate.
+ err = writer.CopyContainer(ContextTag(kTag_GetCertReqMsg_ManufAttest_WeaveCert), cert, certLen);
+ SuccessOrExit(err);
+
+ if (ConfigurationMgr().ManufAttestDeviceICACertsProvisioned())
+ {
+ size_t caCertsLen = 0;
+
+ // Determine the length of the manufacturer attestation device intermediate CA certificates.
+ err = ConfigurationMgr().GetManufAttestDeviceICACerts((uint8_t *)NULL, 0, caCertsLen);
+ SuccessOrExit(err);
+
+ // If needed, allocate larger buffer to hold the intermediate CA certificates.
+ if (caCertsLen > certLen)
+ {
+ MemoryFree(cert);
+
+ cert = static_cast<uint8_t *>(MemoryAlloc(caCertsLen));
+ VerifyOrExit(cert != NULL, err = WEAVE_ERROR_NO_MEMORY);
+ }
+
+ // Read the manufacturer attestation device intermediate CA certificates.
+ err = ConfigurationMgr().GetManufAttestDeviceICACerts(cert, caCertsLen, caCertsLen);
+ SuccessOrExit(err);
+
+ // Copy encoded manufacturer attestation device intermediate CA certificates.
+ err = writer.CopyContainer(ContextTag(kTag_GetCertReqMsg_ManufAttest_WeaveRelCerts), cert, caCertsLen);
+ SuccessOrExit(err);
+ }
+
+exit:
+ if (cert != NULL)
+ {
+ MemoryFree(cert);
+ }
+ return err;
+}
+
+WEAVE_ERROR CertificateProvisioningClient::GenerateAndEncodeMASig(const uint8_t * data, uint16_t dataLen, TLVWriter & writer)
+{
+ WEAVE_ERROR err;
+ uint8_t * privKey = NULL;
+ size_t privKeyLen = 0;
+ nl::Weave::Platform::Security::SHA256 sha256;
+ uint8_t hash[SHA256::kHashLength];
+
+ // Determine the length of the manufacturer attestation device private key.
+ err = ConfigurationMgr().GetDevicePrivateKey((uint8_t *)NULL, 0, privKeyLen);
+ SuccessOrExit(err);
+
+ // Fail if no manufacturer attestation device private key has been configured.
+ VerifyOrExit(privKeyLen != 0, err = WEAVE_ERROR_KEY_NOT_FOUND);
+
+ // Create a temporary buffer to hold the manufacturer attestation device private key.
+ privKey = static_cast<uint8_t *>(MemoryAlloc(privKeyLen));
+ VerifyOrExit(privKey != NULL, err = WEAVE_ERROR_NO_MEMORY);
+
+ // Read the manufacturer attestation device private key.
+ err = ConfigurationMgr().GetDevicePrivateKey(privKey, privKeyLen, privKeyLen);
+ SuccessOrExit(err);
+
+ // Calculate data hash.
+ sha256.Begin();
+ sha256.AddData(data, dataLen);
+ sha256.Finish(hash);
+
+ // Encode manufacturer attestation device signature algorithm: ECDSAWithSHA256.
+ err = writer.Put(ContextTag(kTag_GetCertReqMsg_ManufAttestSigAlgo), static_cast<uint16_t>(ASN1::kOID_SigAlgo_ECDSAWithSHA256));
+ SuccessOrExit(err);
+
+ // Generate and encode manufacturer attestation device signature.
+ err = GenerateAndEncodeWeaveECDSASignature(writer, ContextTag(kTag_GetCertReqMsg_ManufAttestSig_ECDSA),
+ hash, SHA256::kHashLength, privKey, privKeyLen);
+ SuccessOrExit(err);
+
+exit:
+ if (privKey != NULL)
+ {
+ MemoryFree(privKey);
+ }
+ return err;
+}
+
+// ===== Members for internal use by this class only.
+
+void CertificateProvisioningClient::OnPlatformEvent(const WeaveDeviceEvent * event)
+{
+ // If a tunnel to the service has been established...
+ // OR if service connectivity has been established (e.g. via Thread)...
+ if ((event->Type == DeviceEventType::kServiceTunnelStateChange &&
+ event->ServiceTunnelStateChange.Result == kConnectivity_Established) ||
+ (event->Type == DeviceEventType::kServiceConnectivityChange &&
+ event->ServiceConnectivityChange.Overall.Result == kConnectivity_Established))
+ {
+ // If the system is waiting for the service connectivity to be established,
+ // initiate the Certificate Provisioning now.
+ if (mWaitingForServiceConnectivity)
+ {
+ StartCertificateProvisioning();
+ }
+ }
+}
+
+void CertificateProvisioningClient::StartCertificateProvisioning(void)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ // If the system does not currently have a tunnel established with the service,
+ // AND the system does not have service connectivity by some other means (e.g. Thread)
+ // wait a period of time for connectivity to be established.
+ if (!ConnectivityMgr().HaveServiceConnectivity() && !ConnectivityMgr().IsServiceTunnelConnected())
+ {
+ mWaitingForServiceConnectivity = true;
+
+ err = SystemLayer.StartTimer(WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_CONNECTIVITY_TIMEOUT,
+ HandleServiceConnectivityTimeout, this);
+ SuccessOrExit(err);
+ ExitNow();
+
+ WeaveLogProgress(DeviceLayer, "Waiting for service connectivity to complete RegisterServicePairDevice action");
+ }
+
+ mWaitingForServiceConnectivity = false;
+ SystemLayer.CancelTimer(HandleServiceConnectivityTimeout, this);
+
+ WeaveLogProgress(DeviceLayer, "Initiating communication with Service Provisioning service");
+
+ // Create a binding and begin the process of preparing it for talking to the Certificate Provisioning
+ // service. When this completes HandleCertProvBindingEvent will be called with a BindingReady event.
+ mBinding = nl::Weave::DeviceLayer::ExchangeMgr.NewBinding(HandleCertProvBindingEvent, NULL);
+ VerifyOrExit(mBinding != NULL, err = WEAVE_ERROR_NO_MEMORY);
+ err = mBinding->BeginConfiguration()
+ .Target_ServiceEndpoint(WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_ENDPOINT_ID)
+ .Transport_UDP_WRM()
+ .Exchange_ResponseTimeoutMsec(WEAVE_DEVICE_CONFIG_GET_CERTIFICATE_REQUEST_TIMEOUT)
+ .Security_SharedCASESession()
+ .PrepareBinding();
+ SuccessOrExit(err);
+
+ err = mCertProvEngine.Init(mBinding, this, this, CertProvClientEventHandler, this);
+ SuccessOrExit(err);
+
+exit:
+ if (err != WEAVE_NO_ERROR)
+ {
+ HandleCertificateProvisioningResult(err, kWeaveProfile_Common, Profiles::Common::kStatus_InternalError);
+ }
+}
+
+void CertificateProvisioningClient::SendGetCertificateRequest(void)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ WeaveLogProgress(DeviceLayer, "Sending GetCertificateRequest to Certificate Provisioning service");
+
+ err = mCertProvEngine.StartCertificateProvisioning(mReqType, mDoManufAttest);
+ SuccessOrExit(err);
+
+exit:
+ if (err != WEAVE_NO_ERROR)
+ {
+ HandleCertificateProvisioningResult(err, kWeaveProfile_Common, Profiles::Common::kStatus_InternalError);
+ }
+}
+
+void CertificateProvisioningClient::HandleCertificateProvisioningResult(WEAVE_ERROR err, uint32_t statusReportProfileId, uint16_t statusReportStatusCode)
+{
+ // Close the binding if necessary.
+ if (mBinding != NULL)
+ {
+ mBinding->Close();
+ mBinding = NULL;
+ }
+
+ if (err != WEAVE_NO_ERROR)
+ {
+ WeaveLogError(DeviceLayer, "Certificate Provisioning failed with %s: %s",
+ (err == WEAVE_ERROR_STATUS_REPORT_RECEIVED) ? "status report from service" : "local error",
+ (err == WEAVE_ERROR_STATUS_REPORT_RECEIVED)
+ ? ::nl::StatusReportStr(statusReportProfileId, statusReportStatusCode)
+ : ::nl::ErrorStr(err));
+
+ // Choose an appropriate StatusReport to return if not already given.
+ if (statusReportProfileId == 0 && statusReportStatusCode == 0)
+ {
+ if (err == WEAVE_ERROR_TIMEOUT)
+ {
+ statusReportProfileId = kWeaveProfile_Security;
+ statusReportStatusCode = Profiles::Security::kStatusCode_ServiceCommunicationError;
+ }
+ else
+ {
+ statusReportProfileId = kWeaveProfile_Common;
+ statusReportStatusCode = Profiles::Common::kStatus_InternalError;
+ }
+ }
+
+ // TODO: Error CallBack to the the Calling Application.
+ }
+}
+
+void CertificateProvisioningClient::HandleServiceConnectivityTimeout(System::Layer * aSystemLayer, void * aAppState, System::Error aErr)
+{
+ CertificateProvisioningClient *client = static_cast<CertificateProvisioningClient *>(aAppState);
+
+ client->HandleCertificateProvisioningResult(WEAVE_ERROR_TIMEOUT, 0, 0);
+}
+
+void CertificateProvisioningClient::HandleCertProvBindingEvent(void * appState, Binding::EventType eventType,
+ const Binding::InEventParam & inParam, Binding::OutEventParam & outParam)
+{
+ uint32_t statusReportProfileId;
+ uint16_t statusReportStatusCode;
+ CertificateProvisioningClient *client = static_cast<CertificateProvisioningClient *>(appState);
+
+ switch (eventType)
+ {
+ case Binding::kEvent_BindingReady:
+ client->SendGetCertificateRequest();
+ break;
+ case Binding::kEvent_PrepareFailed:
+ if (inParam.PrepareFailed.StatusReport != NULL)
+ {
+ statusReportProfileId = inParam.PrepareFailed.StatusReport->mProfileId;
+ statusReportStatusCode = inParam.PrepareFailed.StatusReport->mStatusCode;
+ }
+ else
+ {
+ statusReportProfileId = kWeaveProfile_Security;
+ statusReportStatusCode = Profiles::Security::kStatusCode_ServiceCommunicationError;
+ }
+ client->HandleCertificateProvisioningResult(inParam.PrepareFailed.Reason,
+ statusReportProfileId, statusReportStatusCode);
+ break;
+ default:
+ Binding::DefaultEventHandler(appState, eventType, inParam, outParam);
+ break;
+ }
+}
+
+#endif // WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace Weave
+} // namespace nl
diff --git a/src/adaptations/device-layer/DeviceControlServer.cpp b/src/adaptations/device-layer/DeviceControlServer.cpp
index 51fec14..c4fd215 100644
--- a/src/adaptations/device-layer/DeviceControlServer.cpp
+++ b/src/adaptations/device-layer/DeviceControlServer.cpp
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -109,6 +110,21 @@
ThreadStackMgr().ClearThreadProvision();
#endif // WEAVE_DEVICE_CONFIG_ENABLE_THREAD
}
+
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ // If a credentials config request has been requested, clear the credential
+ // data, if present.
+ if ((resetFlags & kResetConfigFlag_Credentials) != 0)
+ {
+ WeaveLogProgress(DeviceLayer, "Reset credentials");
+ tmpErr = ConfigurationMgr().ClearDeviceCredentials();
+ if (tmpErr != WEAVE_NO_ERROR)
+ {
+ WeaveLogProgress(DeviceLayer, "ConfigurationMgr().ClearDeviceCredentials() failed: %s", ErrorStr(tmpErr));
+ err = (err == WEAVE_NO_ERROR) ? tmpErr : err;
+ }
+ }
+#endif // WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
}
return err;
@@ -171,7 +187,8 @@
}
const uint16_t supportedResetOps =
- (kResetConfigFlag_NetworkConfig | kResetConfigFlag_FabricConfig | kResetConfigFlag_ServiceConfig);
+ (kResetConfigFlag_NetworkConfig | kResetConfigFlag_FabricConfig |
+ kResetConfigFlag_ServiceConfig | kResetConfigFlag_Credentials);
// Otherwise, verify the requested reset operation is supported.
return (resetFlags == kResetConfigFlag_All || (resetFlags & ~supportedResetOps) == 0);
@@ -213,5 +230,3 @@
} // namespace DeviceLayer
} // namespace Weave
} // namespace nl
-
-
diff --git a/src/adaptations/device-layer/ESP32/BLEManagerImpl.cpp b/src/adaptations/device-layer/ESP32/BLEManagerImpl.cpp
index 9107270..8c06ac2 100644
--- a/src/adaptations/device-layer/ESP32/BLEManagerImpl.cpp
+++ b/src/adaptations/device-layer/ESP32/BLEManagerImpl.cpp
@@ -245,6 +245,7 @@
case DeviceEventType::kFabricMembershipChange:
case DeviceEventType::kServiceProvisioningChange:
case DeviceEventType::kAccountPairingChange:
+ case DeviceEventType::kDeviceCredentialsChange:
// If WOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
// device's provisioning state, then automatically disable WoBLE advertising if the device
@@ -1302,4 +1303,3 @@
} // namespace nl
#endif // WEAVE_DEVICE_CONFIG_ENABLE_WOBLE
-
diff --git a/src/adaptations/device-layer/ESP32/ConnectivityManagerImpl.cpp b/src/adaptations/device-layer/ESP32/ConnectivityManagerImpl.cpp
index 93e26bd..f94ec81 100644
--- a/src/adaptations/device-layer/ESP32/ConnectivityManagerImpl.cpp
+++ b/src/adaptations/device-layer/ESP32/ConnectivityManagerImpl.cpp
@@ -525,18 +525,19 @@
DriveServiceTunnelState();
}
-#if !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING
+#if !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING || WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
- // Handle account pairing changes.
- else if (event->Type == DeviceEventType::kAccountPairingChange)
- {
- // When account pairing successfully completes, if the tunnel to the
- // service is subject to routing restrictions (imposed because at the time
- // the tunnel was established the device was not paired to an account)
+ // Handle account pairing and device credentials changes.
+ else if (((event->Type == DeviceEventType::kAccountPairingChange) && event->AccountPairingChange.IsPairedToAccount) ||
+ ((event->Type == DeviceEventType::kDeviceCredentialsChange) && event->DeviceCredentialsChange.AreCredentialsProvisioned))
+ {
+ // When account pairing successfully completes or new device credentials
+ // provisioned, if the tunnel to the service is subject to routing restrictions
+ // (imposed because at the time the tunnel was established the device was
+ // not paired to an account or the device only had initial self-signed certificate)
// then force the tunnel to close. This will result in the tunnel being
// re-established, which should lift the service-side restrictions.
- if (event->AccountPairingChange.IsPairedToAccount &&
- GetFlag(mFlags, kFlag_ServiceTunnelStarted) &&
+ if (GetFlag(mFlags, kFlag_ServiceTunnelStarted) &&
ServiceTunnelAgent.IsTunnelRoutingRestricted())
{
WeaveLogProgress(DeviceLayer, "Restarting service tunnel to lift routing restrictions");
@@ -546,7 +547,7 @@
}
}
-#endif // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING
+#endif // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING || WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
}
void ConnectivityManagerImpl::_OnWiFiScanDone()
diff --git a/src/adaptations/device-layer/ESP32/ESP32Config.cpp b/src/adaptations/device-layer/ESP32/ESP32Config.cpp
index 4202160..17160f6 100644
--- a/src/adaptations/device-layer/ESP32/ESP32Config.cpp
+++ b/src/adaptations/device-layer/ESP32/ESP32Config.cpp
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -40,27 +41,32 @@
const char ESP32Config::kConfigNamespace_WeaveCounters[] = "weave-counters";
// Keys stored in the weave-factory namespace
-const ESP32Config::Key ESP32Config::kConfigKey_SerialNum = { kConfigNamespace_WeaveFactory, "serial-num" };
-const ESP32Config::Key ESP32Config::kConfigKey_DeviceId = { kConfigNamespace_WeaveFactory, "device-id" };
-const ESP32Config::Key ESP32Config::kConfigKey_DeviceCert = { kConfigNamespace_WeaveFactory, "device-cert" };
-const ESP32Config::Key ESP32Config::kConfigKey_DevicePrivateKey = { kConfigNamespace_WeaveFactory, "device-key" };
-const ESP32Config::Key ESP32Config::kConfigKey_ProductRevision = { kConfigNamespace_WeaveFactory, "product-rev" };
-const ESP32Config::Key ESP32Config::kConfigKey_ManufacturingDate = { kConfigNamespace_WeaveFactory, "mfg-date" };
-const ESP32Config::Key ESP32Config::kConfigKey_PairingCode = { kConfigNamespace_WeaveFactory, "pairing-code" };
+const ESP32Config::Key ESP32Config::kConfigKey_SerialNum = { kConfigNamespace_WeaveFactory, "serial-num" };
+const ESP32Config::Key ESP32Config::kConfigKey_ManufAttestDeviceId = { kConfigNamespace_WeaveFactory, "ma-device-id" };
+const ESP32Config::Key ESP32Config::kConfigKey_ManufAttestDeviceCert = { kConfigNamespace_WeaveFactory, "ma-device-cert" };
+const ESP32Config::Key ESP32Config::kConfigKey_ManufAttestDeviceICACerts = { kConfigNamespace_WeaveFactory, "ma-device-ca-certs" };
+const ESP32Config::Key ESP32Config::kConfigKey_ManufAttestDevicePrivateKey = { kConfigNamespace_WeaveFactory, "ma-device-key" };
+const ESP32Config::Key ESP32Config::kConfigKey_ProductRevision = { kConfigNamespace_WeaveFactory, "product-rev" };
+const ESP32Config::Key ESP32Config::kConfigKey_ManufacturingDate = { kConfigNamespace_WeaveFactory, "mfg-date" };
+const ESP32Config::Key ESP32Config::kConfigKey_PairingCode = { kConfigNamespace_WeaveFactory, "pairing-code" };
// Keys stored in the weave-config namespace
-const ESP32Config::Key ESP32Config::kConfigKey_FabricId = { kConfigNamespace_WeaveConfig, "fabric-id" };
-const ESP32Config::Key ESP32Config::kConfigKey_ServiceConfig = { kConfigNamespace_WeaveConfig, "service-config" };
-const ESP32Config::Key ESP32Config::kConfigKey_PairedAccountId = { kConfigNamespace_WeaveConfig, "account-id" };
-const ESP32Config::Key ESP32Config::kConfigKey_ServiceId = { kConfigNamespace_WeaveConfig, "service-id" };
-const ESP32Config::Key ESP32Config::kConfigKey_FabricSecret = { kConfigNamespace_WeaveConfig, "fabric-secret" };
-const ESP32Config::Key ESP32Config::kConfigKey_GroupKeyIndex = { kConfigNamespace_WeaveConfig, "group-key-index" };
-const ESP32Config::Key ESP32Config::kConfigKey_LastUsedEpochKeyId = { kConfigNamespace_WeaveConfig, "last-ek-id" };
-const ESP32Config::Key ESP32Config::kConfigKey_FailSafeArmed = { kConfigNamespace_WeaveConfig, "fail-safe-armed" };
-const ESP32Config::Key ESP32Config::kConfigKey_WiFiStationSecType = { kConfigNamespace_WeaveConfig, "sta-sec-type" };
+const ESP32Config::Key ESP32Config::kConfigKey_FabricId = { kConfigNamespace_WeaveConfig, "fabric-id" };
+const ESP32Config::Key ESP32Config::kConfigKey_ServiceConfig = { kConfigNamespace_WeaveConfig, "service-config" };
+const ESP32Config::Key ESP32Config::kConfigKey_PairedAccountId = { kConfigNamespace_WeaveConfig, "account-id" };
+const ESP32Config::Key ESP32Config::kConfigKey_ServiceId = { kConfigNamespace_WeaveConfig, "service-id" };
+const ESP32Config::Key ESP32Config::kConfigKey_FabricSecret = { kConfigNamespace_WeaveConfig, "fabric-secret" };
+const ESP32Config::Key ESP32Config::kConfigKey_GroupKeyIndex = { kConfigNamespace_WeaveConfig, "group-key-index" };
+const ESP32Config::Key ESP32Config::kConfigKey_LastUsedEpochKeyId = { kConfigNamespace_WeaveConfig, "last-ek-id" };
+const ESP32Config::Key ESP32Config::kConfigKey_FailSafeArmed = { kConfigNamespace_WeaveConfig, "fail-safe-armed" };
+const ESP32Config::Key ESP32Config::kConfigKey_WiFiStationSecType = { kConfigNamespace_WeaveConfig, "sta-sec-type" };
+const ESP32Config::Key ESP32Config::kConfigKey_OperationalDeviceId = { kConfigNamespace_WeaveConfig, "op-device-id" };
+const ESP32Config::Key ESP32Config::kConfigKey_OperationalDeviceCert = { kConfigNamespace_WeaveConfig, "op-device-cert" };
+const ESP32Config::Key ESP32Config::kConfigKey_OperationalDeviceICACerts = { kConfigNamespace_WeaveConfig, "op-device-ca-certs" };
+const ESP32Config::Key ESP32Config::kConfigKey_OperationalDevicePrivateKey = { kConfigNamespace_WeaveConfig, "op-device-key" };
// Prefix used for NVS keys that contain Weave group encryption keys.
-const char ESP32Config::kGroupKeyNamePrefix[] = "gk-";
+const char ESP32Config::kGroupKeyNamePrefix[] = "gk-";
WEAVE_ERROR ESP32Config::ReadConfigValue(Key key, bool & val)
@@ -126,15 +132,15 @@
SuccessOrExit(err);
needClose = true;
- // Special case the DeviceId value, optionally allowing it to be read as a blob containing a 64-bit
- // big-endian integer, instead of a u64 value.
+ // Special case the ManufAttestDeviceId value, optionally allowing it to be read as a blob containing
+ // a 64-bit big-endian integer, instead of a u64 value.
//
// The ESP32 development environment provides a tool for pre-populating the NVS partition using
// values from a CSV file. This tool is convenient for provisioning devices during manufacturing.
- // However currently the tool does not support pre-populating u64 values such as DeviceId. Thus
- // we allow DeviceId to be stored as a blob instead.
+ // However currently the tool does not support pre-populating u64 values such as ManufAttestDeviceId.
+ // Thus we allow ManufAttestDeviceId to be stored as a blob instead.
//
- if (key == kConfigKey_DeviceId)
+ if (key == kConfigKey_ManufAttestDeviceId)
{
uint8_t deviceIdBytes[sizeof(uint64_t)];
size_t deviceIdLen = sizeof(deviceIdBytes);
diff --git a/src/adaptations/device-layer/Makefile.am b/src/adaptations/device-layer/Makefile.am
index 0812312..9a87a3b 100644
--- a/src/adaptations/device-layer/Makefile.am
+++ b/src/adaptations/device-layer/Makefile.am
@@ -66,6 +66,7 @@
include/Weave/DeviceLayer/WeaveDeviceEvent.h \
include/Weave/DeviceLayer/WeaveDeviceLayer.h \
include/Weave/DeviceLayer/internal/BLEManager.h \
+ include/Weave/DeviceLayer/internal/CertificateProvisioningClient.h \
include/Weave/DeviceLayer/internal/DeviceControlServer.h \
include/Weave/DeviceLayer/internal/DeviceDescriptionServer.h \
include/Weave/DeviceLayer/internal/DeviceIdentityTraitDataSource.h \
@@ -111,6 +112,7 @@
libDeviceLayer_a_SOURCES = \
CASEAuth.cpp \
+ CertificateProvisioningClient.cpp \
DeviceControlServer.cpp \
DeviceDescriptionServer.cpp \
DeviceIdentityTraitDataSource.cpp \
diff --git a/src/adaptations/device-layer/Makefile.in b/src/adaptations/device-layer/Makefile.in
index 7586211..70634a4 100644
--- a/src/adaptations/device-layer/Makefile.in
+++ b/src/adaptations/device-layer/Makefile.in
@@ -216,13 +216,13 @@
libDeviceLayer_a_AR = $(AR) $(ARFLAGS)
libDeviceLayer_a_LIBADD =
am__libDeviceLayer_a_SOURCES_DIST = CASEAuth.cpp \
- DeviceControlServer.cpp DeviceDescriptionServer.cpp \
- DeviceIdentityTraitDataSource.cpp DeviceNetworkInfo.cpp \
- EchoServer.cpp EventLogging.cpp FabricProvisioningServer.cpp \
- GeneralUtils.cpp Globals.cpp NetworkTelemetryManager.cpp \
- PersistedStorage.cpp ServiceDirectoryManager.cpp \
- ServiceProvisioningServer.cpp ServiceTunnelAgent.cpp \
- SystemEventSupport.cpp SystemTimerSupport.cpp \
+ CertificateProvisioningClient.cpp DeviceControlServer.cpp \
+ DeviceDescriptionServer.cpp DeviceIdentityTraitDataSource.cpp \
+ DeviceNetworkInfo.cpp EchoServer.cpp EventLogging.cpp \
+ FabricProvisioningServer.cpp GeneralUtils.cpp Globals.cpp \
+ NetworkTelemetryManager.cpp PersistedStorage.cpp \
+ ServiceDirectoryManager.cpp ServiceProvisioningServer.cpp \
+ ServiceTunnelAgent.cpp SystemEventSupport.cpp SystemTimerSupport.cpp \
TestDeviceIds.cpp TimeSyncManager.cpp TraitManager.cpp \
trait-support/nest/trait/firmware/SoftwareUpdateTrait.cpp \
trait-support/nest/trait/network/TelemetryNetworkTrait.cpp \
@@ -280,6 +280,7 @@
@CONFIG_DEVICE_LAYER_TRUE@@WEAVE_DEVICE_LAYER_TARGET_NRF5_TRUE@ LwIP/libDeviceLayer_a-WarmSupport.$(OBJEXT)
@CONFIG_DEVICE_LAYER_TRUE@am_libDeviceLayer_a_OBJECTS = \
@CONFIG_DEVICE_LAYER_TRUE@ libDeviceLayer_a-CASEAuth.$(OBJEXT) \
+@CONFIG_DEVICE_LAYER_TRUE@ libDeviceLayer_a-CertificateProvisioningClient.$(OBJEXT) \
@CONFIG_DEVICE_LAYER_TRUE@ libDeviceLayer_a-DeviceControlServer.$(OBJEXT) \
@CONFIG_DEVICE_LAYER_TRUE@ libDeviceLayer_a-DeviceDescriptionServer.$(OBJEXT) \
@CONFIG_DEVICE_LAYER_TRUE@ libDeviceLayer_a-DeviceIdentityTraitDataSource.$(OBJEXT) \
@@ -679,6 +680,7 @@
include/Weave/DeviceLayer/WeaveDeviceEvent.h \
include/Weave/DeviceLayer/WeaveDeviceLayer.h \
include/Weave/DeviceLayer/internal/BLEManager.h \
+ include/Weave/DeviceLayer/internal/CertificateProvisioningClient.h \
include/Weave/DeviceLayer/internal/DeviceControlServer.h \
include/Weave/DeviceLayer/internal/DeviceDescriptionServer.h \
include/Weave/DeviceLayer/internal/DeviceIdentityTraitDataSource.h \
@@ -720,6 +722,7 @@
@CONFIG_DEVICE_LAYER_TRUE@ $(NULL)
@CONFIG_DEVICE_LAYER_TRUE@libDeviceLayer_a_SOURCES = CASEAuth.cpp \
+@CONFIG_DEVICE_LAYER_TRUE@ CertificateProvisioningClient.cpp \
@CONFIG_DEVICE_LAYER_TRUE@ DeviceControlServer.cpp \
@CONFIG_DEVICE_LAYER_TRUE@ DeviceDescriptionServer.cpp \
@CONFIG_DEVICE_LAYER_TRUE@ DeviceIdentityTraitDataSource.cpp \
@@ -973,6 +976,7 @@
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDeviceLayer_a-CASEAuth.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDeviceLayer_a-CertificateProvisioningClient.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDeviceLayer_a-DeviceControlServer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDeviceLayer_a-DeviceDescriptionServer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libDeviceLayer_a-DeviceIdentityTraitDataSource.Po@am__quote@
@@ -1067,6 +1071,20 @@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libDeviceLayer_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libDeviceLayer_a-CASEAuth.obj `if test -f 'CASEAuth.cpp'; then $(CYGPATH_W) 'CASEAuth.cpp'; else $(CYGPATH_W) '$(srcdir)/CASEAuth.cpp'; fi`
+libDeviceLayer_a-CertificateProvisioningClient.o: CertificateProvisioningClient.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libDeviceLayer_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libDeviceLayer_a-CertificateProvisioningClient.o -MD -MP -MF $(DEPDIR)/libDeviceLayer_a-CertificateProvisioningClient.Tpo -c -o libDeviceLayer_a-CertificateProvisioningClient.o `test -f 'CertificateProvisioningClient.cpp' || echo '$(srcdir)/'`CertificateProvisioningClient.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libDeviceLayer_a-CertificateProvisioningClient.Tpo $(DEPDIR)/libDeviceLayer_a-CertificateProvisioningClient.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CertificateProvisioningClient.cpp' object='libDeviceLayer_a-CertificateProvisioningClient.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libDeviceLayer_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libDeviceLayer_a-CertificateProvisioningClient.o `test -f 'CertificateProvisioningClient.cpp' || echo '$(srcdir)/'`CertificateProvisioningClient.cpp
+
+libDeviceLayer_a-CertificateProvisioningClient.obj: CertificateProvisioningClient.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libDeviceLayer_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libDeviceLayer_a-CertificateProvisioningClient.obj -MD -MP -MF $(DEPDIR)/libDeviceLayer_a-CertificateProvisioningClient.Tpo -c -o libDeviceLayer_a-CertificateProvisioningClient.obj `if test -f 'CertificateProvisioningClient.cpp'; then $(CYGPATH_W) 'CertificateProvisioningClient.cpp'; else $(CYGPATH_W) '$(srcdir)/CertificateProvisioningClient.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libDeviceLayer_a-CertificateProvisioningClient.Tpo $(DEPDIR)/libDeviceLayer_a-CertificateProvisioningClient.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CertificateProvisioningClient.cpp' object='libDeviceLayer_a-CertificateProvisioningClient.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libDeviceLayer_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libDeviceLayer_a-CertificateProvisioningClient.obj `if test -f 'CertificateProvisioningClient.cpp'; then $(CYGPATH_W) 'CertificateProvisioningClient.cpp'; else $(CYGPATH_W) '$(srcdir)/CertificateProvisioningClient.cpp'; fi`
+
libDeviceLayer_a-DeviceControlServer.o: DeviceControlServer.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libDeviceLayer_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libDeviceLayer_a-DeviceControlServer.o -MD -MP -MF $(DEPDIR)/libDeviceLayer_a-DeviceControlServer.Tpo -c -o libDeviceLayer_a-DeviceControlServer.o `test -f 'DeviceControlServer.cpp' || echo '$(srcdir)/'`DeviceControlServer.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libDeviceLayer_a-DeviceControlServer.Tpo $(DEPDIR)/libDeviceLayer_a-DeviceControlServer.Po
diff --git a/src/adaptations/device-layer/ServiceProvisioningServer.cpp b/src/adaptations/device-layer/ServiceProvisioningServer.cpp
index c0de161..95d2187 100644
--- a/src/adaptations/device-layer/ServiceProvisioningServer.cpp
+++ b/src/adaptations/device-layer/ServiceProvisioningServer.cpp
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -22,14 +23,19 @@
using namespace ::nl;
using namespace ::nl::Weave;
+using namespace ::nl::Weave::TLV;
using namespace ::nl::Weave::Profiles;
using namespace ::nl::Weave::Profiles::ServiceProvisioning;
+using namespace ::nl::Weave::Profiles::Security;
namespace nl {
namespace Weave {
namespace DeviceLayer {
namespace Internal {
+using ::nl::Weave::Platform::Security::MemoryAlloc;
+using ::nl::Weave::Platform::Security::MemoryFree;
+
ServiceProvisioningServer ServiceProvisioningServer::sInstance;
WEAVE_ERROR ServiceProvisioningServer::Init(void)
@@ -91,7 +97,12 @@
PlatformMgr().PostEvent(&event);
}
-#if !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+
+ // Initiate the process of sending a GetCertificateRequest to the Certificate Provisioning service.
+ PlatformMgr().ScheduleWork(AsyncStartCertificateProvisioning);
+
+#elif !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING
// Initiate the process of sending a PairDeviceToAccount request to the Service Provisioning service.
PlatformMgr().ScheduleWork(AsyncStartPairDeviceToAccount);
@@ -304,6 +315,15 @@
mProvServiceBinding = NULL;
}
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ // If necessary, free memory allocated for the certificate provisioning engine.
+ if (mCertProvClient != NULL)
+ {
+ MemoryFree(mCertProvClient);
+ mCertProvClient = NULL;
+ }
+#endif // WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+
// Return immediately if for some reason the client's RegisterServicePairAccount request
// is no longer pending. Note that, even if the PairDeviceToAccount request succeeded,
// the device must clear the persisted service configuration in this case because it has
@@ -374,6 +394,33 @@
}
}
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+void ServiceProvisioningServer::AsyncStartCertificateProvisioning(intptr_t arg)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ // Allocate temporary memory to hold the certificate provisioning client.
+ sInstance.mCertProvClient = static_cast<CertificateProvisioningClient *>(MemoryAlloc(sizeof(CertificateProvisioningClient)));
+ VerifyOrExit(sInstance.mCertProvClient != NULL, err = WEAVE_ERROR_NO_MEMORY);
+
+ // Initialize certificate provisioning client.
+ err = sInstance.mCertProvClient->Init(WeaveCertProvEngine::kReqType_GetInitialOpDeviceCert, sInstance.EncodeGetCertificateRequestAuthInfo);
+ SuccessOrExit(err);
+
+ // Start certificate provisioning.
+ sInstance.mCertProvClient->StartCertificateProvisioning();
+
+exit:
+ if (err != WEAVE_NO_ERROR)
+ {
+ MemoryFree(sInstance.mCertProvClient);
+ sInstance.mCertProvClient = NULL;
+
+ sInstance.HandlePairDeviceToAccountResult(err, kWeaveProfile_Common, Profiles::Common::kStatus_InternalServerProblem);
+ }
+}
+#endif // WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+
void ServiceProvisioningServer::AsyncStartPairDeviceToAccount(intptr_t arg)
{
sInstance.StartPairDeviceToAccount();
@@ -415,6 +462,23 @@
}
}
+WEAVE_ERROR ServiceProvisioningServer::EncodeGetCertificateRequestAuthInfo(TLVWriter & writer)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ const RegisterServicePairAccountMessage & regServiceMsg = sInstance.mCurClientOpMsg.RegisterServicePairAccount;
+
+ // Encode pairing token.
+ err = writer.PutBytes(ContextTag(kTag_GetCertReqMsg_Authorize_PairingToken), regServiceMsg.PairingToken, regServiceMsg.PairingTokenLen);
+ SuccessOrExit(err);
+
+ // Encode pairing initialization data.
+ err = writer.PutBytes(ContextTag(kTag_GetCertReqMsg_Authorize_PairingInitData), regServiceMsg.PairingInitData, regServiceMsg.PairingInitDataLen);
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
#else // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING
void ServiceProvisioningServer::HandlePairDeviceToAccountResult(WEAVE_ERROR err, uint32_t statusReportProfileId, uint16_t statusReportStatusCode)
diff --git a/src/adaptations/device-layer/TestDeviceIds.cpp b/src/adaptations/device-layer/TestDeviceIds.cpp
index b0d828d..2b6bae0 100644
--- a/src/adaptations/device-layer/TestDeviceIds.cpp
+++ b/src/adaptations/device-layer/TestDeviceIds.cpp
@@ -8805,7 +8805,28 @@
#if WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
+const uint8_t TestDeviceICACert[] =
+{
+ 0xD5, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x30, 0x01, 0x08, 0x0C, 0x39, 0x7C, 0x12, 0xA3, 0x49,
+ 0xC7, 0x28, 0x24, 0x02, 0x05, 0x37, 0x03, 0x27, 0x13, 0x02, 0x00, 0x00, 0xEE, 0xEE, 0x30, 0xB4,
+ 0x18, 0x18, 0x26, 0x04, 0x80, 0x41, 0x1B, 0x23, 0x26, 0x05, 0x7F, 0xFF, 0xFF, 0x52, 0x37, 0x06,
+ 0x27, 0x11, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0xB4, 0x18, 0x18, 0x24, 0x07, 0x02, 0x26, 0x08,
+ 0x25, 0x00, 0x5A, 0x23, 0x30, 0x0A, 0x39, 0x04, 0xB9, 0x1D, 0xF2, 0x01, 0x7B, 0xA9, 0x4B, 0xB3,
+ 0x5D, 0x81, 0x70, 0x80, 0x9E, 0xE3, 0xA9, 0x86, 0xC4, 0x47, 0x23, 0xD7, 0xDC, 0xB0, 0x1E, 0x68,
+ 0xC4, 0xB5, 0x6D, 0x0B, 0xF1, 0xEA, 0x10, 0xC5, 0x53, 0x55, 0x43, 0x52, 0x66, 0x6A, 0xF9, 0xB2,
+ 0x66, 0x41, 0xFC, 0x2F, 0xDE, 0x83, 0xDE, 0x4B, 0xD2, 0xF1, 0xBB, 0x81, 0x02, 0x09, 0x16, 0x74,
+ 0x35, 0x83, 0x29, 0x01, 0x18, 0x35, 0x82, 0x29, 0x01, 0x24, 0x02, 0x05, 0x18, 0x35, 0x84, 0x29,
+ 0x01, 0x36, 0x02, 0x04, 0x02, 0x04, 0x01, 0x18, 0x18, 0x35, 0x81, 0x30, 0x02, 0x08, 0x43, 0x4E,
+ 0x72, 0x88, 0x39, 0xDA, 0x6C, 0xC7, 0x18, 0x35, 0x80, 0x30, 0x02, 0x08, 0x44, 0xE3, 0x40, 0x38,
+ 0xA9, 0xD4, 0xB5, 0xA7, 0x18, 0x35, 0x0C, 0x30, 0x01, 0x19, 0x00, 0xEA, 0x20, 0x41, 0xC9, 0x4F,
+ 0xDE, 0xBE, 0xA6, 0x8B, 0x9D, 0x43, 0xD8, 0x84, 0x4D, 0x06, 0xD2, 0x2F, 0xD2, 0x49, 0x9E, 0x46,
+ 0x49, 0x1D, 0x1F, 0x30, 0x02, 0x19, 0x00, 0xF2, 0xB2, 0x39, 0xC6, 0xFB, 0x13, 0x92, 0x3C, 0x7A,
+ 0xAB, 0x79, 0x04, 0x67, 0x78, 0xCB, 0xFE, 0xE1, 0x80, 0x26, 0x4A, 0x35, 0xCF, 0x02, 0x1C, 0x18,
+ 0x18,
+};
+
const uint16_t TestDeviceCertLength = sizeof(TestDeviceCert);
+const uint16_t TestDeviceICACertLength = sizeof(TestDeviceICACert);
const uint16_t TestDevicePrivateKeyLength = sizeof(TestDevicePrivateKey);
#endif // WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/ConfigurationManager.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/ConfigurationManager.h
index e23ba39..4fd6bcd 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/ConfigurationManager.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/ConfigurationManager.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -77,7 +78,12 @@
uint8_t & hour, uint8_t & minute, uint8_t & second);
WEAVE_ERROR GetDeviceId(uint64_t & deviceId);
WEAVE_ERROR GetDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen);
+ WEAVE_ERROR GetDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen);
WEAVE_ERROR GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen);
+ WEAVE_ERROR GetManufAttestDeviceId(uint64_t & deviceId);
+ WEAVE_ERROR GetManufAttestDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen);
+ WEAVE_ERROR GetManufAttestDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen);
+ WEAVE_ERROR GetManufAttestDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen);
WEAVE_ERROR GetPairingCode(char * buf, size_t bufSize, size_t & pairingCodeLen);
WEAVE_ERROR GetServiceId(uint64_t & serviceId);
WEAVE_ERROR GetFabricId(uint64_t & fabricId);
@@ -92,7 +98,14 @@
WEAVE_ERROR StoreProductRevision(uint16_t productRev);
WEAVE_ERROR StoreFabricId(uint64_t fabricId);
WEAVE_ERROR StoreDeviceCertificate(const uint8_t * cert, size_t certLen);
+ WEAVE_ERROR StoreDeviceICACerts(const uint8_t * certs, size_t certsLen);
WEAVE_ERROR StoreDevicePrivateKey(const uint8_t * key, size_t keyLen);
+ WEAVE_ERROR StoreDeviceCredentials(uint64_t deviceId, const uint8_t * cert, size_t certLen, const uint8_t * key, size_t keyLen);
+ WEAVE_ERROR ClearDeviceCredentials(void);
+ WEAVE_ERROR StoreManufAttestDeviceId(uint64_t deviceId);
+ WEAVE_ERROR StoreManufAttestDeviceCertificate(const uint8_t * cert, size_t certLen);
+ WEAVE_ERROR StoreManufAttestDeviceICACerts(const uint8_t * certs, size_t certsLen);
+ WEAVE_ERROR StoreManufAttestDevicePrivateKey(const uint8_t * key, size_t keyLen);
WEAVE_ERROR StorePairingCode(const char * pairingCode, size_t pairingCodeLen);
WEAVE_ERROR StoreServiceProvisioningData(uint64_t serviceId, const uint8_t * serviceConfig, size_t serviceConfigLen, const char * accountId, size_t accountIdLen);
WEAVE_ERROR ClearServiceProvisioningData();
@@ -111,6 +124,11 @@
bool IsPairedToAccount();
bool IsMemberOfFabric();
bool IsFullyProvisioned();
+ bool DeviceCredentialsProvisioned();
+ bool DeviceICACertsProvisioned();
+ bool ManufAttestDeviceICACertsProvisioned();
+ bool UseManufAttestCredentialsAsOperational();
+ void UseManufAttestCredentialsAsOperational(bool val);
void InitiateFactoryReset();
@@ -249,11 +267,36 @@
return static_cast<ImplClass*>(this)->_GetDeviceCertificate(buf, bufSize, certLen);
}
+inline WEAVE_ERROR ConfigurationManager::GetDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen)
+{
+ return static_cast<ImplClass*>(this)->_GetDeviceICACerts(buf, bufSize, certsLen);
+}
+
inline WEAVE_ERROR ConfigurationManager::GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
{
return static_cast<ImplClass*>(this)->_GetDevicePrivateKey(buf, bufSize, keyLen);
}
+inline WEAVE_ERROR ConfigurationManager::GetManufAttestDeviceId(uint64_t & deviceId)
+{
+ return static_cast<ImplClass*>(this)->_GetManufAttestDeviceId(deviceId);
+}
+
+inline WEAVE_ERROR ConfigurationManager::GetManufAttestDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen)
+{
+ return static_cast<ImplClass*>(this)->_GetManufAttestDeviceCertificate(buf, bufSize, certLen);
+}
+
+inline WEAVE_ERROR ConfigurationManager::GetManufAttestDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen)
+{
+ return static_cast<ImplClass*>(this)->_GetManufAttestDeviceICACerts(buf, bufSize, certsLen);
+}
+
+inline WEAVE_ERROR ConfigurationManager::GetManufAttestDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
+{
+ return static_cast<ImplClass*>(this)->_GetManufAttestDevicePrivateKey(buf, bufSize, keyLen);
+}
+
inline WEAVE_ERROR ConfigurationManager::GetPairingCode(char * buf, size_t bufSize, size_t & pairingCodeLen)
{
return static_cast<ImplClass*>(this)->_GetPairingCode(buf, bufSize, pairingCodeLen);
@@ -319,11 +362,46 @@
return static_cast<ImplClass*>(this)->_StoreDeviceCertificate(cert, certLen);
}
+inline WEAVE_ERROR ConfigurationManager::StoreDeviceICACerts(const uint8_t * certs, size_t certsLen)
+{
+ return static_cast<ImplClass*>(this)->_StoreDeviceICACerts(certs, certsLen);
+}
+
inline WEAVE_ERROR ConfigurationManager::StoreDevicePrivateKey(const uint8_t * key, size_t keyLen)
{
return static_cast<ImplClass*>(this)->_StoreDevicePrivateKey(key, keyLen);
}
+inline WEAVE_ERROR ConfigurationManager::StoreDeviceCredentials(uint64_t deviceId, const uint8_t * cert, size_t certLen, const uint8_t * key, size_t keyLen)
+{
+ return static_cast<ImplClass*>(this)->_StoreDeviceCredentials(deviceId, cert, certLen, key, keyLen);
+}
+
+inline WEAVE_ERROR ConfigurationManager::ClearDeviceCredentials(void)
+{
+ return static_cast<ImplClass*>(this)->_ClearDeviceCredentials();
+}
+
+inline WEAVE_ERROR ConfigurationManager::StoreManufAttestDeviceId(uint64_t deviceId)
+{
+ return static_cast<ImplClass*>(this)->_StoreManufAttestDeviceId(deviceId);
+}
+
+inline WEAVE_ERROR ConfigurationManager::StoreManufAttestDeviceCertificate(const uint8_t * cert, size_t certLen)
+{
+ return static_cast<ImplClass*>(this)->_StoreManufAttestDeviceCertificate(cert, certLen);
+}
+
+inline WEAVE_ERROR ConfigurationManager::StoreManufAttestDeviceICACerts(const uint8_t * certs, size_t certsLen)
+{
+ return static_cast<ImplClass*>(this)->_StoreManufAttestDeviceICACerts(certs, certsLen);
+}
+
+inline WEAVE_ERROR ConfigurationManager::StoreManufAttestDevicePrivateKey(const uint8_t * key, size_t keyLen)
+{
+ return static_cast<ImplClass*>(this)->_StoreManufAttestDevicePrivateKey(key, keyLen);
+}
+
inline WEAVE_ERROR ConfigurationManager::StorePairingCode(const char * pairingCode, size_t pairingCodeLen)
{
return static_cast<ImplClass*>(this)->_StorePairingCode(pairingCode, pairingCodeLen);
@@ -404,6 +482,31 @@
return static_cast<ImplClass*>(this)->_IsFullyProvisioned();
}
+inline bool ConfigurationManager::DeviceCredentialsProvisioned()
+{
+ return static_cast<ImplClass*>(this)->_DeviceCredentialsProvisioned();
+}
+
+inline bool ConfigurationManager::DeviceICACertsProvisioned()
+{
+ return static_cast<ImplClass*>(this)->_DeviceICACertsProvisioned();
+}
+
+inline bool ConfigurationManager::ManufAttestDeviceICACertsProvisioned()
+{
+ return static_cast<ImplClass*>(this)->_ManufAttestDeviceICACertsProvisioned();
+}
+
+inline bool ConfigurationManager::UseManufAttestCredentialsAsOperational()
+{
+ return static_cast<ImplClass*>(this)->_UseManufAttestCredentialsAsOperational();
+}
+
+inline void ConfigurationManager::UseManufAttestCredentialsAsOperational(bool val)
+{
+ static_cast<ImplClass*>(this)->_UseManufAttestCredentialsAsOperational(val);
+}
+
inline void ConfigurationManager::InitiateFactoryReset()
{
static_cast<ImplClass*>(this)->_InitiateFactoryReset();
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/ESP32/ESP32Config.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/ESP32/ESP32Config.h
index 56d8b32..a108404 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/ESP32/ESP32Config.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/ESP32/ESP32Config.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -53,9 +54,10 @@
// Key definitions for well-known keys.
static const Key kConfigKey_SerialNum;
- static const Key kConfigKey_DeviceId;
- static const Key kConfigKey_DeviceCert;
- static const Key kConfigKey_DevicePrivateKey;
+ static const Key kConfigKey_ManufAttestDeviceId;
+ static const Key kConfigKey_ManufAttestDeviceCert;
+ static const Key kConfigKey_ManufAttestDeviceICACerts;
+ static const Key kConfigKey_ManufAttestDevicePrivateKey;
static const Key kConfigKey_ProductRevision;
static const Key kConfigKey_ManufacturingDate;
static const Key kConfigKey_PairingCode;
@@ -68,6 +70,10 @@
static const Key kConfigKey_LastUsedEpochKeyId;
static const Key kConfigKey_FailSafeArmed;
static const Key kConfigKey_WiFiStationSecType;
+ static const Key kConfigKey_OperationalDeviceId;
+ static const Key kConfigKey_OperationalDeviceCert;
+ static const Key kConfigKey_OperationalDeviceICACerts;
+ static const Key kConfigKey_OperationalDevicePrivateKey;
static const char kGroupKeyNamePrefix[];
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/PlatformManager.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/PlatformManager.h
index 37d5fd4..ca3eb53 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/PlatformManager.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/PlatformManager.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -36,6 +37,7 @@
class TraitManager;
class TimeSyncManager;
namespace Internal {
+class CertificateProvisioningClient;
class FabricProvisioningServer;
class ServiceProvisioningServer;
class BLEManagerImpl;
@@ -81,6 +83,7 @@
friend class ConfigurationManagerImpl;
friend class TraitManager;
friend class TimeSyncManager;
+ friend class Internal::CertificateProvisioningClient;
friend class Internal::FabricProvisioningServer;
friend class Internal::ServiceProvisioningServer;
friend class Internal::BLEManagerImpl;
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceConfig.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceConfig.h
index 85dde96..076ea1f 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceConfig.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceConfig.h
@@ -480,6 +480,56 @@
#define WEAVE_DEVICE_CONFIG_SERVICE_PROVISIONING_REQUEST_TIMEOUT 10000
#endif
+// -------------------- Operational Device Credentials Configuration --------------------
+
+/**
+ * WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ *
+ * Enable the ephemeral operational device credentials feature.
+ *
+ * When enabled device creates and uses its ephemeral operational credentials:
+ * - operational device id
+ * - operational device certificate
+ * - operational device private key
+ * Device uses these credentials to authenticate and communicate to other Weave nodes.
+ */
+#ifndef WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+#define WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS 1
+#endif
+
+/**
+ * WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_ENDPOINT_ID
+ *
+ * Specifies the service endpoint id of the Weave Certificate Provisioning service. When a device
+ * undergoes certificate provisioning, this is the endpoint to which it will send its Get Certificate
+ * request.
+ */
+#ifndef WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_ENDPOINT_ID
+#define WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_ENDPOINT_ID 0x18B4300200000016ULL
+#endif
+
+/**
+ * WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_CONNECTIVITY_TIMEOUT
+ *
+ * The maximum amount of time (in milliseconds) to wait for service connectivity during the device
+ * certificate provisioning step. More specifically, this is the maximum amount of time the device will
+ * wait for connectivity to be established with the service at the point where the device waiting
+ * to send a Get Certificate request to the Certificate Provisioning service.
+ */
+#ifndef WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_CONNECTIVITY_TIMEOUT
+#define WEAVE_DEVICE_CONFIG_CERTIFICATE_PROVISIONING_CONNECTIVITY_TIMEOUT 10000
+#endif
+
+/**
+ * WEAVE_DEVICE_CONFIG_GET_CERTIFICATE_REQUEST_TIMEOUT
+ *
+ * Specifies the maximum amount of time (in milliseconds) to wait for a response from the Certificate
+ * Provisioning service.
+ */
+#ifndef WEAVE_DEVICE_CONFIG_GET_CERTIFICATE_REQUEST_TIMEOUT
+#define WEAVE_DEVICE_CONFIG_GET_CERTIFICATE_REQUEST_TIMEOUT 10000
+#endif
+
// -------------------- Thread Configuration --------------------
/**
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceEvent.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceEvent.h
index 194204c..91ce198 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceEvent.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/WeaveDeviceEvent.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -196,6 +197,13 @@
* Signals that the state of WoBLE advertising has changed.
*/
kWoBLEAdvertisingChange,
+
+ /**
+ * Device Credentials Change
+ *
+ * Signals that the device's credentials has changed
+ */
+ kDeviceCredentialsChange,
};
/**
@@ -397,6 +405,10 @@
{
ActivityChange Result;
} WoBLEAdvertisingChange;
+ struct
+ {
+ bool AreCredentialsProvisioned;
+ } DeviceCredentialsChange;
};
void Clear() { memset(this, 0, sizeof(*this)); }
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/CertificateProvisioningClient.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/CertificateProvisioningClient.h
new file mode 100644
index 0000000..c413e3b
--- /dev/null
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/CertificateProvisioningClient.h
@@ -0,0 +1,114 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Defines the Device Layer CertificateProvisioningClient object.
+ */
+
+#ifndef CERTIFICATE_PROVISIONING_CLIENT_H
+#define CERTIFICATE_PROVISIONING_CLIENT_H
+
+#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
+#include <Weave/Profiles/security/WeaveCertProvisioning.h>
+
+namespace nl {
+namespace Weave {
+namespace DeviceLayer {
+namespace Internal {
+
+using nl::Weave::Profiles::Security::CertProvisioning::WeaveCertProvEngine;
+
+extern WEAVE_ERROR GenerateAndStoreOperationalDeviceCredentials(uint64_t deviceId = kNodeIdNotSpecified);
+
+/**
+ * Implements the Weave Certificate Provisioning profile for a Weave device.
+ */
+class CertificateProvisioningClient final
+ : public ::nl::Weave::Profiles::Security::CertProvisioning::WeaveNodeOpAuthDelegate,
+ public ::nl::Weave::Profiles::Security::CertProvisioning::WeaveNodeManufAttestDelegate
+{
+
+public:
+
+ /**
+ * This function is the callback that is invoked by Certificate Provisioning Client to add
+ * authorization info to the GetCertificateRequest message in a TLV form to the supplied TLV writer.
+ *
+ * @param[in] writer A reference to a TLV writer to write request authorization data.
+ */
+ typedef WEAVE_ERROR (* EncodeReqAuthInfoFunct)(TLVWriter & writer);
+
+ // ===== Members for internal use by other Device Layer components.
+
+ WEAVE_ERROR Init(uint8_t reqType);
+ WEAVE_ERROR Init(uint8_t reqType, EncodeReqAuthInfoFunct encodeReqAuthInfo);
+ void OnPlatformEvent(const WeaveDeviceEvent * event);
+
+ // ===== Methods that implement the WeaveNodeOpAuthDelegate interface
+
+ WEAVE_ERROR EncodeOpCert(TLVWriter & writer, uint64_t tag) __OVERRIDE;
+ WEAVE_ERROR EncodeOpRelatedCerts(TLVWriter & writer, uint64_t tag) __OVERRIDE;
+ WEAVE_ERROR GenerateAndEncodeOpSig(const uint8_t * hash, uint8_t hashLen, TLVWriter & writer, uint64_t tag) __OVERRIDE;
+
+ // ===== Methods that implement the WeaveNodeManufAttestDelegate interface
+
+ WEAVE_ERROR EncodeMAInfo(TLVWriter & writer) __OVERRIDE;
+ WEAVE_ERROR GenerateAndEncodeMASig(const uint8_t * data, uint16_t dataLen, TLVWriter & writer) __OVERRIDE;
+
+ // ===== Members that override virtual methods on ServiceProvisioningDelegate
+
+ void StartCertificateProvisioning(void);
+ void HandleCertificateProvisioningResult(WEAVE_ERROR localErr, uint32_t serverStatusProfileId, uint16_t serverStatusCode);
+
+private:
+
+ // ===== Members for internal use by this class only.
+
+ WeaveCertProvEngine mCertProvEngine;
+ ::nl::Weave::Binding * mBinding;
+ uint8_t mReqType;
+ bool mDoManufAttest;
+ EncodeReqAuthInfoFunct mEncodeReqAuthInfo;
+ bool mWaitingForServiceConnectivity;
+
+ void SendGetCertificateRequest(void);
+
+ static void HandleServiceConnectivityTimeout(::nl::Weave::System::Layer * layer, void * appState, ::nl::Weave::System::Error err);
+ static void HandleCertProvBindingEvent(void * appState, nl::Weave::Binding::EventType eventType,
+ const nl::Weave::Binding::InEventParam & inParam, nl::Weave::Binding::OutEventParam & outParam);
+ static void CertProvClientEventHandler(void * appState, WeaveCertProvEngine::EventType eventType, const WeaveCertProvEngine::InEventParam & inParam, WeaveCertProvEngine::OutEventParam & outParam);
+
+protected:
+
+ // Construction/destruction limited to subclasses.
+ CertificateProvisioningClient() = default;
+ ~CertificateProvisioningClient() = default;
+
+ // No copy, move or assignment.
+ CertificateProvisioningClient(const CertificateProvisioningClient &) = delete;
+ CertificateProvisioningClient(const CertificateProvisioningClient &&) = delete;
+ CertificateProvisioningClient & operator=(const CertificateProvisioningClient &) = delete;
+};
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace Weave
+} // namespace nl
+
+#endif // CERTIFICATE_PROVISIONING_CLIENT_H
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.h
index 8cb9a15..538fa38 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.h
@@ -97,7 +97,8 @@
kTag_DevicePrivateKey = 3, // [ byte string ] Manufacturer-assigned device key
kTag_PairingCode = 4, // [ utf-8 string ] Pairing code
kTag_ProductRev = 5, // [ uint, 16-bit max ] Product revision
- kTag_MfgDate = 6 // [ utf-8 string ] Manufacturing date
+ kTag_MfgDate = 6, // [ utf-8 string ] Manufacturing date
+ kTag_DeviceICACerts = 7, // [ byte string ] Manufacturer-assigned device intermediate CA certificates
};
/**
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.ipp b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.ipp
index 6a83547..6a79364 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.ipp
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/FactoryProvisioning.ipp
@@ -176,7 +176,7 @@
uint64_t deviceId;
err = reader.Get(deviceId);
SuccessOrExit(err);
- err = ConfigurationMgr().StoreDeviceId(deviceId);
+ err = ConfigurationMgr().StoreManufAttestDeviceId(deviceId);
SuccessOrExit(err);
break;
}
@@ -186,7 +186,17 @@
const uint8_t * cert;
err = reader.GetDataPtr(cert);
SuccessOrExit(err);
- err = ConfigurationMgr().StoreDeviceCertificate(cert, reader.GetLength());
+ err = ConfigurationMgr().StoreManufAttestDeviceCertificate(cert, reader.GetLength());
+ SuccessOrExit(err);
+ break;
+ }
+
+ case FactoryProvisioningData::kTag_DeviceICACerts:
+ {
+ const uint8_t * certs;
+ err = reader.GetDataPtr(certs);
+ SuccessOrExit(err);
+ err = ConfigurationMgr().StoreManufAttestDeviceICACerts(certs, reader.GetLength());
SuccessOrExit(err);
break;
}
@@ -196,7 +206,7 @@
const uint8_t * privKey;
err = reader.GetDataPtr(privKey);
SuccessOrExit(err);
- err = ConfigurationMgr().StoreDevicePrivateKey(privKey, reader.GetLength());
+ err = ConfigurationMgr().StoreManufAttestDevicePrivateKey(privKey, reader.GetLength());
SuccessOrExit(err);
break;
}
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h
index 227c538..ed74c32 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -69,8 +70,20 @@
WEAVE_ERROR _StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen);
WEAVE_ERROR _GetDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen);
WEAVE_ERROR _StoreDeviceCertificate(const uint8_t * cert, size_t certLen);
+ WEAVE_ERROR _GetDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen);
+ WEAVE_ERROR _StoreDeviceICACerts(const uint8_t * certs, size_t certsLen);
WEAVE_ERROR _GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen);
WEAVE_ERROR _StoreDevicePrivateKey(const uint8_t * key, size_t keyLen);
+ WEAVE_ERROR _StoreDeviceCredentials(uint64_t deviceId, const uint8_t * cert, size_t certLen, const uint8_t * key, size_t keyLen);
+ WEAVE_ERROR _ClearDeviceCredentials(void);
+ WEAVE_ERROR _GetManufAttestDeviceId(uint64_t & deviceId);
+ WEAVE_ERROR _StoreManufAttestDeviceId(uint64_t deviceId);
+ WEAVE_ERROR _GetManufAttestDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen);
+ WEAVE_ERROR _StoreManufAttestDeviceCertificate(const uint8_t * cert, size_t certLen);
+ WEAVE_ERROR _GetManufAttestDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen);
+ WEAVE_ERROR _StoreManufAttestDeviceICACerts(const uint8_t * certs, size_t certsLen);
+ WEAVE_ERROR _GetManufAttestDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen);
+ WEAVE_ERROR _StoreManufAttestDevicePrivateKey(const uint8_t * key, size_t keyLen);
WEAVE_ERROR _GetPairingCode(char * buf, size_t bufSize, size_t & pairingCodeLen);
WEAVE_ERROR _StorePairingCode(const char * pairingCode, size_t pairingCodeLen);
WEAVE_ERROR _GetFabricId(uint64_t & fabricId);
@@ -95,14 +108,21 @@
bool _IsPairedToAccount();
bool _IsFullyProvisioned();
WEAVE_ERROR _ComputeProvisioningHash(uint8_t * hashBuf, size_t hashBufSize);
+ bool _DeviceCredentialsProvisioned();
+ bool _DeviceICACertsProvisioned();
+ bool _ManufAttestDeviceICACertsProvisioned();
+ bool _UseManufAttestCredentialsAsOperational();
+ void _UseManufAttestCredentialsAsOperational(bool val);
protected:
enum
{
- kFlag_IsServiceProvisioned = 0x01,
- kFlag_IsMemberOfFabric = 0x02,
- kFlag_IsPairedToAccount = 0x04,
+ kFlag_IsServiceProvisioned = 0x01,
+ kFlag_IsMemberOfFabric = 0x02,
+ kFlag_IsPairedToAccount = 0x04,
+ kFlag_DeviceCredentialsProvisioned = 0x08,
+ kFlag_UseManufAttestCredentialsAsOperational = 0x10,
};
uint8_t mFlags;
@@ -143,4 +163,3 @@
} // namespace nl
#endif // GENERIC_CONFIGURATION_MANAGER_IMPL_H
-
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp
index d5e91d2..a1d6385 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -52,6 +53,7 @@
SetFlag(mFlags, kFlag_IsServiceProvisioned, Impl()->ConfigValueExists(ImplClass::kConfigKey_ServiceConfig));
SetFlag(mFlags, kFlag_IsMemberOfFabric, Impl()->ConfigValueExists(ImplClass::kConfigKey_FabricId));
SetFlag(mFlags, kFlag_IsPairedToAccount, Impl()->ConfigValueExists(ImplClass::kConfigKey_PairedAccountId));
+ SetFlag(mFlags, kFlag_DeviceCredentialsProvisioned, Impl()->ConfigValueExists(ImplClass::kConfigKey_OperationalDeviceCert));
return WEAVE_NO_ERROR;
}
@@ -154,11 +156,11 @@
}
template<class ImplClass>
-WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceId(uint64_t & deviceId)
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufAttestDeviceId(uint64_t & deviceId)
{
WEAVE_ERROR err;
- err = Impl()->ReadConfigValue(ImplClass::kConfigKey_DeviceId, deviceId);
+ err = Impl()->ReadConfigValue(ImplClass::kConfigKey_ManufAttestDeviceId, deviceId);
#if WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
if (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND)
@@ -172,9 +174,9 @@
}
template<class ImplClass>
-WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceId(uint64_t deviceId)
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufAttestDeviceId(uint64_t deviceId)
{
- return Impl()->WriteConfigValue(ImplClass::kConfigKey_DeviceId, deviceId);
+ return Impl()->WriteConfigValue(ImplClass::kConfigKey_ManufAttestDeviceId, deviceId);
}
template<class ImplClass>
@@ -299,11 +301,11 @@
}
template<class ImplClass>
-WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen)
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufAttestDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen)
{
WEAVE_ERROR err;
- err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_DeviceCert, buf, bufSize, certLen);
+ err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_ManufAttestDeviceCert, buf, bufSize, certLen);
#if WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
@@ -326,17 +328,50 @@
}
template<class ImplClass>
-WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceCertificate(const uint8_t * cert, size_t certLen)
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufAttestDeviceCertificate(const uint8_t * cert, size_t certLen)
{
- return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_DeviceCert, cert, certLen);
+ return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_ManufAttestDeviceCert, cert, certLen);
}
template<class ImplClass>
-WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufAttestDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen)
{
WEAVE_ERROR err;
- err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_DevicePrivateKey, buf, bufSize, keyLen);
+ err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_ManufAttestDeviceICACerts, buf, bufSize, certsLen);
+
+#if WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
+
+ if (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND)
+ {
+ certsLen = TestDeviceICACertLength;
+ VerifyOrExit(buf != NULL, err = WEAVE_NO_ERROR);
+ VerifyOrExit(TestDeviceICACertLength <= bufSize, err = WEAVE_ERROR_BUFFER_TOO_SMALL);
+ WeaveLogProgress(DeviceLayer, "Device certificate not found; using default");
+ memcpy(buf, TestDeviceICACert, TestDeviceICACertLength);
+ err = WEAVE_NO_ERROR;
+ }
+
+#endif // WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
+
+ SuccessOrExit(err);
+
+exit:
+ return err;
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufAttestDeviceICACerts(const uint8_t * certs, size_t certsLen)
+{
+ return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_ManufAttestDeviceICACerts, certs, certsLen);
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetManufAttestDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
+{
+ WEAVE_ERROR err;
+
+ err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_ManufAttestDevicePrivateKey, buf, bufSize, keyLen);
#if WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
@@ -359,9 +394,169 @@
}
template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreManufAttestDevicePrivateKey(const uint8_t * key, size_t keyLen)
+{
+ return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_ManufAttestDevicePrivateKey, key, keyLen);
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceId(uint64_t & deviceId)
+{
+ WEAVE_ERROR err;
+
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ if (!_UseManufAttestCredentialsAsOperational())
+ {
+ err = Impl()->ReadConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
+ }
+ else
+#endif
+ {
+ err = Impl()->_GetManufAttestDeviceId(deviceId);
+ }
+
+ return err;
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceId(uint64_t deviceId)
+{
+ return Impl()->WriteConfigValue(ImplClass::kConfigKey_OperationalDeviceId, deviceId);
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceCertificate(uint8_t * buf, size_t bufSize, size_t & certLen)
+{
+ WEAVE_ERROR err;
+
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ if (!_UseManufAttestCredentialsAsOperational())
+ {
+ err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, buf, bufSize, certLen);
+ }
+ else
+#endif
+ {
+ err = Impl()->_GetManufAttestDeviceCertificate(buf, bufSize, certLen);
+ }
+
+ return err;
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceCertificate(const uint8_t * cert, size_t certLen)
+{
+ return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceCert, cert, certLen);
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDeviceICACerts(uint8_t * buf, size_t bufSize, size_t & certsLen)
+{
+ WEAVE_ERROR err;
+
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ if (!_UseManufAttestCredentialsAsOperational())
+ {
+ err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, buf, bufSize, certsLen);
+ }
+ else
+#endif
+ {
+ err = Impl()->_GetManufAttestDeviceICACerts(buf, bufSize, certsLen);
+ }
+
+ return err;
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceICACerts(const uint8_t * certs, size_t certsLen)
+{
+ return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDeviceICACerts, certs, certsLen);
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GetDevicePrivateKey(uint8_t * buf, size_t bufSize, size_t & keyLen)
+{
+ WEAVE_ERROR err;
+
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ if (!_UseManufAttestCredentialsAsOperational())
+ {
+ err = Impl()->ReadConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, buf, bufSize, keyLen);
+ }
+ else
+#endif
+ {
+ err = Impl()->_GetManufAttestDevicePrivateKey(buf, bufSize, keyLen);
+ }
+
+ return err;
+}
+
+template<class ImplClass>
WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDevicePrivateKey(const uint8_t * key, size_t keyLen)
{
- return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_DevicePrivateKey, key, keyLen);
+ return Impl()->WriteConfigValueBin(ImplClass::kConfigKey_OperationalDevicePrivateKey, key, keyLen);
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_StoreDeviceCredentials(uint64_t deviceId, const uint8_t * cert, size_t certLen, const uint8_t * key, size_t keyLen)
+{
+ WEAVE_ERROR err;
+
+ err = Impl()->_StoreDeviceId(deviceId);
+ SuccessOrExit(err);
+
+ err = Impl()->_StoreDeviceCertificate(cert, certLen);
+ SuccessOrExit(err);
+
+ err = Impl()->_StoreDevicePrivateKey(key, keyLen);
+ SuccessOrExit(err);
+
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceICACerts);
+
+ SetFlag(mFlags, kFlag_DeviceCredentialsProvisioned);
+
+ // Post an event alerting other subsystems that the device now new credentials.
+ {
+ WeaveDeviceEvent event;
+ event.Type = DeviceEventType::kDeviceCredentialsChange;
+ event.DeviceCredentialsChange.AreCredentialsProvisioned = true;
+ PlatformMgr().PostEvent(&event);
+ }
+
+exit:
+ if (err != WEAVE_NO_ERROR)
+ {
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceId);
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceCert);
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDevicePrivateKey);
+ ClearFlag(mFlags, kFlag_DeviceCredentialsProvisioned);
+ }
+ return err;
+}
+
+template<class ImplClass>
+WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_ClearDeviceCredentials(void)
+{
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceId);
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceCert);
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDeviceICACerts);
+ Impl()->ClearConfigValue(ImplClass::kConfigKey_OperationalDevicePrivateKey);
+
+ // If necessary, post an event alerting other subsystems to the change in
+ // the certificate state.
+ if (_DeviceCredentialsProvisioned())
+ {
+ WeaveDeviceEvent event;
+ event.Type = DeviceEventType::kDeviceCredentialsChange;
+ event.DeviceCredentialsChange.AreCredentialsProvisioned = false;
+ PlatformMgr().PostEvent(&event);
+ }
+
+ ClearFlag(mFlags, kFlag_DeviceCredentialsProvisioned);
+
+ return WEAVE_NO_ERROR;
}
template<class ImplClass>
@@ -728,6 +923,9 @@
#if !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING
Impl()->IsPairedToAccount() &&
#endif
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ (!Impl()->UseManufAttestCredentialsAsOperational() && Impl()->DeviceCredentialsProvisioned()) &&
+#endif
Impl()->IsMemberOfFabric();
}
@@ -770,7 +968,7 @@
constexpr uint16_t kDeviceIdLen = 16; // 16 hex characters
char inputBuf[kLenFieldLen + kDeviceIdLen + 1]; // +1 for terminator
- err = Impl()->_GetDeviceId(deviceId);
+ err = Impl()->_GetManufAttestDeviceId(deviceId);
SuccessOrExit(err);
snprintf(inputBuf, sizeof(inputBuf), "0010%016" PRIX64, deviceId);
@@ -783,7 +981,7 @@
size_t certLen;
// Determine the length of the device certificate.
- err = Impl()->_GetDeviceCertificate((uint8_t *)NULL, 0, certLen);
+ err = Impl()->_GetManufAttestDeviceCertificate((uint8_t *)NULL, 0, certLen);
SuccessOrExit(err);
// Create a temporary buffer to hold the certificate. (This will also be used for
@@ -793,25 +991,53 @@
VerifyOrExit(dataBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
// Read the certificate.
- err = Impl()->_GetDeviceCertificate(dataBuf, certLen, certLen);
+ err = Impl()->_GetManufAttestDeviceCertificate(dataBuf, certLen, certLen);
SuccessOrExit(err);
// Hash the length and value of the device certificate in base-64 form.
HashLengthAndBase64Value(hash, dataBuf, (uint16_t)certLen);
}
+ // Hash the device intermediate CA certificates
+ if (Impl()->ConfigValueExists(ImplClass::kConfigKey_ManufAttestDeviceICACerts))
+ {
+ size_t certsLen;
+
+ // Determine the length of the device certificate.
+ err = Impl()->_GetManufAttestDeviceICACerts((uint8_t *)NULL, 0, certsLen);
+ SuccessOrExit(err);
+
+ // Allocate larger buffer to hold the intermediate CA certificates.
+ // (This will also be used for the private key).
+ if (certsLen > dataBufSize)
+ {
+ Platform::Security::MemoryFree(dataBuf);
+
+ dataBufSize = certsLen;
+ dataBuf = (uint8_t *)Platform::Security::MemoryAlloc(dataBufSize);
+ VerifyOrExit(dataBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
+ }
+
+ // Read the certificate.
+ err = Impl()->_GetManufAttestDeviceICACerts(dataBuf, certsLen, certsLen);
+ SuccessOrExit(err);
+
+ // Hash the length and value of the device certificate in base-64 form.
+ HashLengthAndBase64Value(hash, dataBuf, (uint16_t)certsLen);
+ }
+
// Hash the device private key
{
size_t keyLen;
// Determine the length of the device private key.
- err = Impl()->_GetDevicePrivateKey((uint8_t *)NULL, 0, keyLen);
+ err = Impl()->_GetManufAttestDevicePrivateKey((uint8_t *)NULL, 0, keyLen);
SuccessOrExit(err);
// Read the private key. (Note that we presume the buffer allocated to hold the certificate
// is big enough to hold the private key. _GetDevicePrivateKey() will return an error in the
// unlikely event that this is not the case.)
- err = Impl()->_GetDevicePrivateKey(dataBuf, dataBufSize, keyLen);
+ err = Impl()->_GetManufAttestDevicePrivateKey(dataBuf, dataBufSize, keyLen);
SuccessOrExit(err);
// Hash the length and value of the private key in base-64 form.
@@ -873,6 +1099,36 @@
}
}
+template<class ImplClass>
+bool GenericConfigurationManagerImpl<ImplClass>::_DeviceCredentialsProvisioned()
+{
+ return ::nl::GetFlag(mFlags, kFlag_DeviceCredentialsProvisioned);
+}
+
+template<class ImplClass>
+bool GenericConfigurationManagerImpl<ImplClass>::_DeviceICACertsProvisioned()
+{
+ return Impl()->ConfigValueExists(ImplClass::kConfigKey_OperationalDeviceICACerts);
+}
+
+template<class ImplClass>
+bool GenericConfigurationManagerImpl<ImplClass>::_ManufAttestDeviceICACertsProvisioned()
+{
+ return Impl()->ConfigValueExists(ImplClass::kConfigKey_ManufAttestDeviceICACerts);
+}
+
+template<class ImplClass>
+bool GenericConfigurationManagerImpl<ImplClass>::_UseManufAttestCredentialsAsOperational()
+{
+ return ::nl::GetFlag(mFlags, kFlag_UseManufAttestCredentialsAsOperational);
+}
+
+template<class ImplClass>
+void GenericConfigurationManagerImpl<ImplClass>::_UseManufAttestCredentialsAsOperational(bool val)
+{
+ SetFlag(mFlags, kFlag_UseManufAttestCredentialsAsOperational, val);
+}
+
#if WEAVE_PROGRESS_LOGGING
template<class ImplClass>
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericPlatformManagerImpl.ipp b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericPlatformManagerImpl.ipp
index 71af0d7..3be554b 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericPlatformManagerImpl.ipp
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/GenericPlatformManagerImpl.ipp
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -28,6 +29,7 @@
#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/PlatformManager.h>
+#include <Weave/DeviceLayer/internal/CertificateProvisioningClient.h>
#include <Weave/DeviceLayer/internal/GenericPlatformManagerImpl.h>
#include <Weave/DeviceLayer/internal/DeviceControlServer.h>
#include <Weave/DeviceLayer/internal/DeviceDescriptionServer.h>
@@ -73,6 +75,27 @@
}
SuccessOrExit(err);
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ if (!ConfigurationMgr().DeviceCredentialsProvisioned())
+ {
+ // If paired to account keep using device manufacturing credentials as operational.
+ if (ConfigurationMgr().IsServiceProvisioned() && ConfigurationMgr().IsPairedToAccount())
+ {
+ ConfigurationMgr().UseManufAttestCredentialsAsOperational(true);
+ }
+ // Otherwise, generate and store new device credentials.
+ else
+ {
+ err = GenerateAndStoreOperationalDeviceCredentials();
+ if (err != WEAVE_NO_ERROR)
+ {
+ WeaveLogError(DeviceLayer, "GenerateAndStoreOperationalDeviceCredentials() failed: %s", ErrorStr(err));
+ }
+ SuccessOrExit(err);
+ }
+ }
+#endif
+
// Initialize the Weave system layer.
new (&SystemLayer) System::Layer();
err = SystemLayer.Init(NULL);
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/ServiceProvisioningServer.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/ServiceProvisioningServer.h
index 364ed65..677d8a7 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/ServiceProvisioningServer.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/ServiceProvisioningServer.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -26,6 +27,7 @@
#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/Profiles/service-provisioning/ServiceProvisioning.h>
+#include <Weave/DeviceLayer/internal/CertificateProvisioningClient.h>
namespace nl {
namespace Weave {
@@ -84,14 +86,19 @@
::nl::Weave::Binding * mProvServiceBinding;
bool mWaitingForServiceConnectivity;
+#if WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
+ CertificateProvisioningClient * mCertProvClient;
+#endif // WEAVE_DEVICE_CONFIG_ENABLE_OPERATIONAL_DEVICE_CREDENTIALS
void StartPairDeviceToAccount(void);
void SendPairDeviceToAccountRequest(void);
+ static void AsyncStartCertificateProvisioning(intptr_t arg);
static void AsyncStartPairDeviceToAccount(intptr_t arg);
static void HandleServiceConnectivityTimeout(::nl::Weave::System::Layer * layer, void * appState, ::nl::Weave::System::Error err);
static void HandleProvServiceBindingEvent(void * appState, nl::Weave::Binding::EventType eventType,
const nl::Weave::Binding::InEventParam & inParam, nl::Weave::Binding::OutEventParam & outParam);
+ static WEAVE_ERROR EncodeGetCertificateRequestAuthInfo(TLVWriter &writer);
protected:
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h
index abec891..8e06465 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h
@@ -44,8 +44,10 @@
#if WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
extern const uint64_t TestDeviceId;
extern const uint8_t TestDeviceCert[];
+extern const uint8_t TestDeviceICACert[];
extern const uint8_t TestDevicePrivateKey[];
extern const uint16_t TestDeviceCertLength;
+extern const uint16_t TestDeviceICACertLength;
extern const uint16_t TestDevicePrivateKeyLength;
#endif // WEAVE_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/testing/ConfigUnitTest.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/testing/ConfigUnitTest.h
index 50676a3..1239bc3 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/testing/ConfigUnitTest.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/internal/testing/ConfigUnitTest.h
@@ -50,12 +50,12 @@
{
uint64_t v = 9872349687345;
- err = ConfigClass::WriteConfigValue(ConfigClass::kConfigKey_DeviceId, v);
+ err = ConfigClass::WriteConfigValue(ConfigClass::kConfigKey_ManufAttestDeviceId, v);
VerifyOrDie(err == WEAVE_NO_ERROR);
v = 0;
- err = ConfigClass::ReadConfigValue(ConfigClass::kConfigKey_DeviceId, v);
+ err = ConfigClass::ReadConfigValue(ConfigClass::kConfigKey_ManufAttestDeviceId, v);
VerifyOrDie(err == WEAVE_NO_ERROR);
VerifyOrDie(v == 9872349687345);
@@ -149,10 +149,10 @@
uint8_t buf[512];
size_t dataLen;
- err = ConfigClass::WriteConfigValueBin(ConfigClass::kConfigKey_DeviceCert, kTestData, sizeof(kTestData));
+ err = ConfigClass::WriteConfigValueBin(ConfigClass::kConfigKey_ManufAttestDeviceCert, kTestData, sizeof(kTestData));
VerifyOrDie(err == WEAVE_NO_ERROR);
- err = ConfigClass::ReadConfigValueBin(ConfigClass::kConfigKey_DeviceCert, buf, sizeof(buf), dataLen);
+ err = ConfigClass::ReadConfigValueBin(ConfigClass::kConfigKey_ManufAttestDeviceCert, buf, sizeof(buf), dataLen);
VerifyOrDie(err == WEAVE_NO_ERROR);
VerifyOrDie(dataLen == sizeof(kTestData));
@@ -164,10 +164,10 @@
uint8_t buf[512];
size_t dataLen;
- err = ConfigClass::WriteConfigValueBin(ConfigClass::kConfigKey_DeviceCert, NULL, 0);
+ err = ConfigClass::WriteConfigValueBin(ConfigClass::kConfigKey_ManufAttestDeviceCert, NULL, 0);
VerifyOrDie(err == WEAVE_NO_ERROR);
- err = ConfigClass::ReadConfigValueBin(ConfigClass::kConfigKey_DeviceCert, buf, sizeof(buf), dataLen);
+ err = ConfigClass::ReadConfigValueBin(ConfigClass::kConfigKey_ManufAttestDeviceCert, buf, sizeof(buf), dataLen);
VerifyOrDie(err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND);
}
@@ -175,13 +175,13 @@
{
bool v;
- v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_DeviceId);
+ v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_ManufAttestDeviceId);
VerifyOrDie(v == true);
v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_FailSafeArmed);
VerifyOrDie(v == true);
- v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_DeviceCert);
+ v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_ManufAttestDeviceCert);
VerifyOrDie(v == false);
}
@@ -192,7 +192,7 @@
err = ConfigClass::FactoryResetConfig();
VerifyOrDie(err == WEAVE_NO_ERROR);
- v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_DeviceId);
+ v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_ManufAttestDeviceId);
VerifyOrDie(v == true);
v = ConfigClass::ConfigValueExists(ConfigClass::kConfigKey_FailSafeArmed);
diff --git a/src/adaptations/device-layer/include/Weave/DeviceLayer/nRF5/nRF5Config.h b/src/adaptations/device-layer/include/Weave/DeviceLayer/nRF5/nRF5Config.h
index 8d40646..b3c8f85 100644
--- a/src/adaptations/device-layer/include/Weave/DeviceLayer/nRF5/nRF5Config.h
+++ b/src/adaptations/device-layer/include/Weave/DeviceLayer/nRF5/nRF5Config.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -79,9 +80,9 @@
// Key definitions for well-known configuration values.
static constexpr Key kConfigKey_SerialNum = NRF5ConfigKey(kFileId_WeaveFactory, 0x0001);
- static constexpr Key kConfigKey_DeviceId = NRF5ConfigKey(kFileId_WeaveFactory, 0x0002);
- static constexpr Key kConfigKey_DeviceCert = NRF5ConfigKey(kFileId_WeaveFactory, 0x0003);
- static constexpr Key kConfigKey_DevicePrivateKey = NRF5ConfigKey(kFileId_WeaveFactory, 0x0004);
+ static constexpr Key kConfigKey_ManufAttestDeviceId = NRF5ConfigKey(kFileId_WeaveFactory, 0x0002);
+ static constexpr Key kConfigKey_ManufAttestDeviceCert = NRF5ConfigKey(kFileId_WeaveFactory, 0x0003);
+ static constexpr Key kConfigKey_ManufAttestDevicePrivateKey = NRF5ConfigKey(kFileId_WeaveFactory, 0x0004);
static constexpr Key kConfigKey_ManufacturingDate = NRF5ConfigKey(kFileId_WeaveFactory, 0x0005);
static constexpr Key kConfigKey_PairingCode = NRF5ConfigKey(kFileId_WeaveFactory, 0x0006);
static constexpr Key kConfigKey_FabricId = NRF5ConfigKey(kFileId_WeaveConfig, 0x0007);
@@ -93,6 +94,11 @@
static constexpr Key kConfigKey_FailSafeArmed = NRF5ConfigKey(kFileId_WeaveConfig, 0x000D);
static constexpr Key kConfigKey_GroupKey = NRF5ConfigKey(kFileId_WeaveConfig, 0x000E);
static constexpr Key kConfigKey_ProductRevision = NRF5ConfigKey(kFileId_WeaveFactory, 0x000F);
+ static constexpr Key kConfigKey_ManufAttestDeviceICACerts = NRF5ConfigKey(kFileId_WeaveFactory, 0x0010);
+ static constexpr Key kConfigKey_OperationalDeviceId = NRF5ConfigKey(kFileId_WeaveConfig, 0x0011);
+ static constexpr Key kConfigKey_OperationalDeviceCert = NRF5ConfigKey(kFileId_WeaveConfig, 0x0012);
+ static constexpr Key kConfigKey_OperationalDeviceICACerts = NRF5ConfigKey(kFileId_WeaveConfig, 0x0013);
+ static constexpr Key kConfigKey_OperationalDevicePrivateKey = NRF5ConfigKey(kFileId_WeaveConfig, 0x0014);
// Range of FDS record keys used to store Weave persisted counter values.
static constexpr uint16_t kPersistedCounterRecordKeyBase = kFDSRecordKeyMin;
diff --git a/src/adaptations/device-layer/nRF5/BLEManagerImpl.cpp b/src/adaptations/device-layer/nRF5/BLEManagerImpl.cpp
index 2ed18c6..5866cc5 100644
--- a/src/adaptations/device-layer/nRF5/BLEManagerImpl.cpp
+++ b/src/adaptations/device-layer/nRF5/BLEManagerImpl.cpp
@@ -282,6 +282,7 @@
case DeviceEventType::kFabricMembershipChange:
case DeviceEventType::kServiceProvisioningChange:
case DeviceEventType::kAccountPairingChange:
+ case DeviceEventType::kDeviceCredentialsChange:
// If WOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
// device's provisioning state, then automatically disable WoBLE advertising if the device
diff --git a/src/adaptations/device-layer/nRF5/nRF5Config.cpp b/src/adaptations/device-layer/nRF5/nRF5Config.cpp
index 5ed4065..483006e 100644
--- a/src/adaptations/device-layer/nRF5/nRF5Config.cpp
+++ b/src/adaptations/device-layer/nRF5/nRF5Config.cpp
@@ -769,13 +769,13 @@
for (int i = 0; i < 100; i++)
{
- err = WriteConfigValueBin(kConfigKey_DeviceCert, kTestData, sizeof(kTestData));
+ err = WriteConfigValueBin(kConfigKey_ManufAttestDeviceCert, kTestData, sizeof(kTestData));
VerifyOrDie(err == WEAVE_NO_ERROR);
vTaskDelay(pdMS_TO_TICKS(50));
}
- err = ReadConfigValueBin(kConfigKey_DeviceCert, buf, sizeof(buf), dataLen);
+ err = ReadConfigValueBin(kConfigKey_ManufAttestDeviceCert, buf, sizeof(buf), dataLen);
VerifyOrDie(err == WEAVE_NO_ERROR);
VerifyOrDie(dataLen == sizeof(kTestData));
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 1c55496..86d266c 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -1061,6 +1061,7 @@
nl_public_WeaveDeviceLayer_internal_header_sources = \
$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/BLEManager.h \
+$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/CertificateProvisioningClient.h \
$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/DeviceControlServer.h \
$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/DeviceDescriptionServer.h \
$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/DeviceIdentityTraitDataSource.h \
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
index 4a97d96..3fac8f6 100644
--- a/src/include/Makefile.in
+++ b/src/include/Makefile.in
@@ -1423,6 +1423,7 @@
@CONFIG_DEVICE_LAYER_TRUE@nl_public_WeaveDeviceLayer_internal_header_sources = \
@CONFIG_DEVICE_LAYER_TRUE@$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/BLEManager.h \
+@CONFIG_DEVICE_LAYER_TRUE@$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/CertificateProvisioningClient.h \
@CONFIG_DEVICE_LAYER_TRUE@$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/DeviceControlServer.h \
@CONFIG_DEVICE_LAYER_TRUE@$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/DeviceDescriptionServer.h \
@CONFIG_DEVICE_LAYER_TRUE@$(nl_public_WeaveDeviceLayer_source_dirstem)/internal/DeviceIdentityTraitDataSource.h \
diff --git a/src/lib/profiles/device-control/DeviceControl.h b/src/lib/profiles/device-control/DeviceControl.h
index 3686718..ab44ce2 100644
--- a/src/lib/profiles/device-control/DeviceControl.h
+++ b/src/lib/profiles/device-control/DeviceControl.h
@@ -1,5 +1,6 @@
/*
*
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
@@ -110,6 +111,7 @@
kResetConfigFlag_NetworkConfig = 0x0001, /**< Reset network configuration information. */
kResetConfigFlag_FabricConfig = 0x0002, /**< Reset fabric configuration information. */
kResetConfigFlag_ServiceConfig = 0x0004, /**< Reset network configuration information. */
+ kResetConfigFlag_Credentials = 0x0008, /**< Reset device credentials. */
kResetConfigFlag_FactoryDefaults = 0x8000 /**< Reset device to full factory defaults. */
};
diff --git a/src/lib/profiles/security/WeaveSecurity.h b/src/lib/profiles/security/WeaveSecurity.h
index 3ea86c9..3c9c428 100644
--- a/src/lib/profiles/security/WeaveSecurity.h
+++ b/src/lib/profiles/security/WeaveSecurity.h
@@ -108,8 +108,9 @@
kStatusCode_InternalKeyError = 16, // The receiver of the Weave message encountered key error.
kStatusCode_NoCommonKeyExportConfiguration = 17, // No common key export protocol configuration supported.
kStatusCode_UnathorizedKeyExportRequest = 18, // An unauthorized key export request.
- kStatusCode_UnathorizedGetCertRequest = 19, // An unauthorized get certificate request.
- kStatusCode_NoNewCertRequired = 20, // No new certificate required.
+ kStatusCode_ServiceCommunicationError = 19, /**< The device could not complete certificate provisioning because it encountered an error when communicating with the service. */
+ kStatusCode_UnathorizedGetCertRequest = 20, /**< An unauthorized get certificate request. */
+ kStatusCode_NoNewCertRequired = 21, /**< No new certificate required. */
};
// Weave Key Error Message Size
diff --git a/src/lib/support/StatusReportStr.cpp b/src/lib/support/StatusReportStr.cpp
index 5ff499e..e52eee4 100644
--- a/src/lib/support/StatusReportStr.cpp
+++ b/src/lib/support/StatusReportStr.cpp
@@ -265,6 +265,7 @@
case Security::kStatusCode_InternalKeyError : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Internal key error"; break;
case Security::kStatusCode_NoCommonKeyExportConfiguration : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] No common key export configuration"; break;
case Security::kStatusCode_UnathorizedKeyExportRequest : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Unauthorized key export request"; break;
+ case Security::kStatusCode_ServiceCommunicationError : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Service communication error"; break;
case Security::kStatusCode_UnathorizedGetCertRequest : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Unauthorized get certificate request"; break;
case Security::kStatusCode_NoNewCertRequired : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] No new certificate required"; break;
default : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ]"; break;