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

Commit 6a35c33

Browse files
author
Jay Logue
committed
Factory Provisioning Tool
-- Implemented a tool for factory provisioning of devices running OpenWeave firmware. The tool is designed to run on a host machine that is connected to a device via some form of debug or control interface. The tool works by injecting provisioning information into the device’s RAM in a special encoded form designed to be easily identified. The device is then instructed to restart, at which point code in the initialization of the OpenWeave Device Layer searches memory for the encoded data, validates it, and writes the contained values to persistent storage in a format appropriate for the platform. The tool is capable of provisioning the following information: Device serial number Manufacturer-assigned Weave device id Manufacturer-assigned certificate and private key Pairing code Product revision number Manufacturing date Provisioning information is specified as command line arguments to the tool. Alternatively, the tool can be instructed read select information (certificate, private key and pairing code) from a provisioning data CSV file, as produced by the weave tool’s “gen-provisioning-data” command, or from an HTTP-based provisioning data server, as is used in Nest factory provisioning. Currently, the tool supports provisioning ESP32 devices using using the ESP32 serial bootloader protocol, and nRF52840 devices using a SEGGER J-Link debug probe.
1 parent b7f3563 commit 6a35c33

20 files changed

+1942
-19
lines changed

certs/development/device/test-dev-provisioning-data.csv

Lines changed: 257 additions & 0 deletions
Large diffs are not rendered by default.

src/adaptations/device-layer/ESP32/ConfigurationManagerImpl.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
#include <Weave/DeviceLayer/ESP32/ESP32Config.h>
3232
#include <Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp>
3333

34+
#if WEAVE_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING
35+
#include <Weave/DeviceLayer/internal/FactoryProvisioning.ipp>
36+
#endif // WEAVE_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING
37+
3438
#include "esp_wifi.h"
3539
#include "nvs_flash.h"
3640
#include "nvs.h"
@@ -89,6 +93,21 @@ WEAVE_ERROR ConfigurationManagerImpl::_Init()
8993
err = gGroupKeyStore.Init();
9094
SuccessOrExit(err);
9195

96+
#if WEAVE_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING
97+
98+
{
99+
FactoryProvisioning factoryProv;
100+
uint8_t * const kInternalSRAM12Start = (uint8_t *)0x3FFAE000;
101+
uint8_t * const kInternalSRAM12End = kInternalSRAM12Start + (328 * 1024) - 1;
102+
103+
// Scan ESP32 Internal SRAM regions 1 and 2 for injected provisioning data and save
104+
// to persistent storage if found.
105+
err = factoryProv.ProvisionDeviceFromRAM(kInternalSRAM12Start, kInternalSRAM12End);
106+
SuccessOrExit(err);
107+
}
108+
109+
#endif // WEAVE_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING
110+
92111
// If the fail-safe was armed when the device last shutdown, initiate a factory reset.
93112
if (_GetFailSafeArmed(failSafeArmed) == WEAVE_NO_ERROR && failSafeArmed)
94113
{

src/adaptations/device-layer/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ noinst_HEADERS = \
7373
include/Weave/DeviceLayer/internal/EchoServer.h \
7474
include/Weave/DeviceLayer/internal/EventLogging.h \
7575
include/Weave/DeviceLayer/internal/FabricProvisioningServer.h \
76+
include/Weave/DeviceLayer/internal/FactoryProvisioning.h \
77+
include/Weave/DeviceLayer/internal/FactoryProvisioning.ipp \
7678
include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h \
7779
include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp \
7880
include/Weave/DeviceLayer/internal/GenericNetworkProvisioningServerImpl.h \

src/adaptations/device-layer/Makefile.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,8 @@ noinst_HEADERS = \
694694
include/Weave/DeviceLayer/internal/EchoServer.h \
695695
include/Weave/DeviceLayer/internal/EventLogging.h \
696696
include/Weave/DeviceLayer/internal/FabricProvisioningServer.h \
697+
include/Weave/DeviceLayer/internal/FactoryProvisioning.h \
698+
include/Weave/DeviceLayer/internal/FactoryProvisioning.ipp \
697699
include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h \
698700
include/Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp \
699701
include/Weave/DeviceLayer/internal/GenericNetworkProvisioningServerImpl.h \

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,15 @@ class ConfigurationManager
8585
WEAVE_ERROR GetPairedAccountId(char * buf, size_t bufSize, size_t & accountIdLen);
8686

8787
WEAVE_ERROR StoreDeviceId(uint64_t deviceId);
88-
WEAVE_ERROR StoreSerialNumber(const char * serialNum);
88+
WEAVE_ERROR StoreSerialNumber(const char * serialNum, size_t serialNumLen);
8989
WEAVE_ERROR StorePrimaryWiFiMACAddress(const uint8_t * buf);
9090
WEAVE_ERROR StorePrimary802154MACAddress(const uint8_t * buf);
91-
WEAVE_ERROR StoreManufacturingDate(const char * mfgDate);
91+
WEAVE_ERROR StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen);
9292
WEAVE_ERROR StoreProductRevision(uint16_t productRev);
9393
WEAVE_ERROR StoreFabricId(uint64_t fabricId);
9494
WEAVE_ERROR StoreDeviceCertificate(const uint8_t * cert, size_t certLen);
9595
WEAVE_ERROR StoreDevicePrivateKey(const uint8_t * key, size_t keyLen);
96-
WEAVE_ERROR StorePairingCode(const char * pairingCode);
96+
WEAVE_ERROR StorePairingCode(const char * pairingCode, size_t pairingCodeLen);
9797
WEAVE_ERROR StoreServiceProvisioningData(uint64_t serviceId, const uint8_t * serviceConfig, size_t serviceConfigLen, const char * accountId, size_t accountIdLen);
9898
WEAVE_ERROR ClearServiceProvisioningData();
9999
WEAVE_ERROR StoreServiceConfig(const uint8_t * serviceConfig, size_t serviceConfigLen);
@@ -281,9 +281,9 @@ inline WEAVE_ERROR ConfigurationManager::StoreDeviceId(uint64_t deviceId)
281281
return static_cast<ImplClass*>(this)->_StoreDeviceId(deviceId);
282282
}
283283

284-
inline WEAVE_ERROR ConfigurationManager::StoreSerialNumber(const char * serialNum)
284+
inline WEAVE_ERROR ConfigurationManager::StoreSerialNumber(const char * serialNum, size_t serialNumLen)
285285
{
286-
return static_cast<ImplClass*>(this)->_StoreSerialNumber(serialNum);
286+
return static_cast<ImplClass*>(this)->_StoreSerialNumber(serialNum, serialNumLen);
287287
}
288288

289289
inline WEAVE_ERROR ConfigurationManager::StorePrimaryWiFiMACAddress(const uint8_t * buf)
@@ -296,9 +296,9 @@ inline WEAVE_ERROR ConfigurationManager::StorePrimary802154MACAddress(const uint
296296
return static_cast<ImplClass*>(this)->_StorePrimary802154MACAddress(buf);
297297
}
298298

299-
inline WEAVE_ERROR ConfigurationManager::StoreManufacturingDate(const char * mfgDate)
299+
inline WEAVE_ERROR ConfigurationManager::StoreManufacturingDate(const char * mfgDate, size_t mfgDateLen)
300300
{
301-
return static_cast<ImplClass*>(this)->_StoreManufacturingDate(mfgDate);
301+
return static_cast<ImplClass*>(this)->_StoreManufacturingDate(mfgDate, mfgDateLen);
302302
}
303303

304304
inline WEAVE_ERROR ConfigurationManager::StoreProductRevision(uint16_t productRev)
@@ -321,9 +321,9 @@ inline WEAVE_ERROR ConfigurationManager::StoreDevicePrivateKey(const uint8_t * k
321321
return static_cast<ImplClass*>(this)->_StoreDevicePrivateKey(key, keyLen);
322322
}
323323

324-
inline WEAVE_ERROR ConfigurationManager::StorePairingCode(const char * pairingCode)
324+
inline WEAVE_ERROR ConfigurationManager::StorePairingCode(const char * pairingCode, size_t pairingCodeLen)
325325
{
326-
return static_cast<ImplClass*>(this)->_StorePairingCode(pairingCode);
326+
return static_cast<ImplClass*>(this)->_StorePairingCode(pairingCode, pairingCodeLen);
327327
}
328328

329329
inline WEAVE_ERROR ConfigurationManager::StoreServiceProvisioningData(uint64_t serviceId, const uint8_t * serviceConfig, size_t serviceConfigLen, const char * accountId, size_t accountIdLen)

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@
105105
#define WEAVE_DEVICE_CONFIG_LOG_MESSAGE_MAX_SIZE 256
106106
#endif
107107

108+
/**
109+
* WEAVE_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING
110+
*
111+
* Enable the device factory provisioning feature.
112+
*
113+
* The factory provisioning feature allows factory or developer-supplied provisioning information
114+
* to be injected into a device at boot time and automatically stored in persistent storage.
115+
*/
116+
#ifndef WEAVE_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING
117+
#define WEAVE_DEVICE_CONFIG_ENABLE_FACTORY_PROVISIONING 1
118+
#endif
119+
108120
// -------------------- Device Identification Configuration --------------------
109121

110122
/**
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
*
3+
* Copyright (c) 2019 Google LLC.
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/**
20+
* @file
21+
* Support for device factory provisioning.
22+
*/
23+
24+
#ifndef FACTORY_PROVISIONING_H
25+
#define FACTORY_PROVISIONING_H
26+
27+
#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
28+
29+
namespace nl {
30+
namespace Weave {
31+
namespace TLV {
32+
class TLVReader;
33+
} // namespace TLV
34+
} // namespace Weave
35+
} // namespace nl
36+
37+
namespace nl {
38+
namespace Weave {
39+
namespace DeviceLayer {
40+
namespace Internal {
41+
42+
/**
43+
* Supports device factory provisioning at boot time.
44+
*
45+
* The factory provisioning feature allows factory or developer-supplied provisioning information
46+
* to be injected into a device at boot time and automatically stored in persistent storage.
47+
* Provisioning information is written into device memory (typically RAM) by an external tool,
48+
* where it is picked by the OpenWeave initialization code and stored into persistent storage
49+
* early in the boot process.
50+
*
51+
* The factory provisioning feature allows the following values to be set:
52+
*
53+
* - Device Serial number
54+
* - Manufacturer-assigned Device Id
55+
* - Manufacturer-assigned Device Certificate
56+
* - Manufacturer-assigned Device Key
57+
* - Pairing Code
58+
* - Product Revision
59+
* - Manufacturing Date
60+
*
61+
* This template class provides a default base implementation of the device provisioning feature
62+
* that can be specialized as needed by compile-time derivation.
63+
*/
64+
template<class DerivedClass>
65+
class FactoryProvisioningBase
66+
{
67+
public:
68+
WEAVE_ERROR ProvisionDeviceFromRAM(uint8_t * memRangeStart, uint8_t * memRangeEnd);
69+
70+
protected:
71+
bool LocateProvisioningData(uint8_t * memRangeStart, uint8_t * memRangeEnd, uint8_t * & dataStart, size_t & dataLen);
72+
WEAVE_ERROR StoreProvisioningData(TLV::TLVReader & reader);
73+
WEAVE_ERROR StoreProvisioningValue(uint8_t tagNum, TLV::TLVReader & reader);
74+
75+
private:
76+
DerivedClass * Derived() { return static_cast<DerivedClass *>(this); }
77+
};
78+
79+
/**
80+
* Default implementation of the device factory provisioning feature.
81+
*/
82+
class FactoryProvisioning
83+
: public FactoryProvisioningBase<FactoryProvisioning>
84+
{
85+
};
86+
87+
namespace FactoryProvisioningData {
88+
89+
/**
90+
* Context-specific tags for Device Provisioning Data Weave TLV structure
91+
*/
92+
enum
93+
{
94+
kTag_SerialNumber = 0, // [ utf-8 string ] Serial number
95+
kTag_DeviceId = 1, // [ uint, 64-bit max ] Manufacturer-assigned device id
96+
kTag_DeviceCert = 2, // [ byte string ] Manufacturer-assigned device certificate
97+
kTag_DevicePrivateKey = 3, // [ byte string ] Manufacturer-assigned device key
98+
kTag_PairingCode = 4, // [ utf-8 string ] Pairing code
99+
kTag_ProductRev = 5, // [ uint, 16-bit max ] Product revision
100+
kTag_MfgDate = 6 // [ utf-8 string ] Manufacturing date
101+
};
102+
103+
/**
104+
* Marker used to mark the location of device provisioning data in memory.
105+
*/
106+
const char kMarker[] = "^OW-PROV-DATA^";
107+
constexpr size_t kMarkerLen = sizeof(kMarker) - 1;
108+
109+
} // namespace FactoryProvisioningData
110+
111+
112+
113+
} // namespace Internal
114+
} // namespace DeviceLayer
115+
} // namespace Weave
116+
} // namespace nl
117+
118+
#endif // FACTORY_PROVISIONING_H

0 commit comments

Comments
 (0)