blob: 6225f91d2c62e8884f720588b70522682e8590b4 [file] [log] [blame]
John Wedig2098dab2021-09-14 13:56:28 -07001
2#include "estoraged.hpp"
3
John Edward Broadbent59dffa62022-01-13 17:41:32 -08004#include "cryptErase.hpp"
John Wedigb810c922021-11-17 16:38:03 -08005#include "cryptsetupInterface.hpp"
John Edward Broadbent7f2ab642021-11-11 21:00:38 -08006#include "pattern.hpp"
John Edward Broadbent605085a2021-11-05 13:45:45 -07007#include "sanitize.hpp"
John Edward Broadbente6ffe702021-10-14 14:03:11 -07008#include "verifyDriveGeometry.hpp"
John Edward Broadbent4bc8a102021-12-30 16:11:49 -08009#include "zero.hpp"
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080010
John Wedigb810c922021-11-17 16:38:03 -080011#include <libcryptsetup.h>
12#include <openssl/rand.h>
John Wedigb810c922021-11-17 16:38:03 -080013
14#include <phosphor-logging/lg2.hpp>
John Wedig67a47442022-04-05 17:21:29 -070015#include <sdbusplus/asio/object_server.hpp>
John Wedig972c3fa2021-12-29 17:30:41 -080016#include <xyz/openbmc_project/Common/error.hpp>
John Wedigb810c922021-11-17 16:38:03 -080017
Ed Tanous82897c32022-02-21 14:11:59 -080018#include <cstdlib>
John Wedigb810c922021-11-17 16:38:03 -080019#include <filesystem>
John Wedig2098dab2021-09-14 13:56:28 -070020#include <iostream>
John Wedig67a47442022-04-05 17:21:29 -070021#include <string>
John Wedigb810c922021-11-17 16:38:03 -080022#include <string_view>
John Wedig67a47442022-04-05 17:21:29 -070023#include <utility>
John Wedig2098dab2021-09-14 13:56:28 -070024#include <vector>
25
26namespace estoraged
27{
28
John Wedig972c3fa2021-12-29 17:30:41 -080029using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
30using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
31using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest;
John Wedig67a47442022-04-05 17:21:29 -070032using sdbusplus::xyz::openbmc_project::Inventory::Item::server::Volume;
John Wedigb810c922021-11-17 16:38:03 -080033
John Wedig67a47442022-04-05 17:21:29 -070034EStoraged::EStoraged(sdbusplus::asio::object_server& server,
35 const std::string& devPath, const std::string& luksName,
36 uint64_t size,
37 std::unique_ptr<CryptsetupInterface> cryptInterface,
38 std::unique_ptr<FilesystemInterface> fsInterface) :
39 devPath(devPath),
40 containerName(luksName), mountPoint("/mnt/" + luksName + "_fs"),
41 lockedProperty(false), cryptIface(std::move(cryptInterface)),
42 fsIface(std::move(fsInterface)), objectServer(server)
43{
44 /* Get the filename of the device (without "/dev/"). */
45 std::string deviceName = std::filesystem::path(devPath).filename().string();
46 /* DBus object path */
47 std::string path = "/xyz/openbmc_project/inventory/storage/" + deviceName;
48
49 /* Add Volume interface. */
50 volumeInterface = objectServer.add_interface(
51 path, "xyz.openbmc_project.Inventory.Item.Volume");
52 volumeInterface->register_method(
53 "FormatLuks", [this](const std::vector<uint8_t>& password,
54 Volume::FilesystemType type) {
55 this->formatLuks(password, type);
56 });
57 volumeInterface->register_method(
58 "Erase",
59 [this](Volume::EraseMethod eraseType) { this->erase(eraseType); });
60 volumeInterface->register_method("Lock", [this]() { this->lock(); });
61 volumeInterface->register_method(
62 "Unlock",
63 [this](std::vector<uint8_t>& password) { this->unlock(password); });
64 volumeInterface->register_method(
65 "ChangePassword", [this](const std::vector<uint8_t>& oldPassword,
66 const std::vector<uint8_t>& newPassword) {
67 this->changePassword(oldPassword, newPassword);
68 });
69 volumeInterface->register_property_r(
70 "Locked", lockedProperty, sdbusplus::vtable::property_::emits_change,
71 [this](bool& value) {
72 value = this->isLocked();
73 return value;
74 });
75
76 /* Add Drive interface. */
77 driveInterface = objectServer.add_interface(
78 path, "xyz.openbmc_project.Inventory.Item.Drive");
79 driveInterface->register_property("Capacity", size);
80
81 volumeInterface->initialize();
82 driveInterface->initialize();
83}
84
85EStoraged::~EStoraged()
86{
87 objectServer.remove_interface(volumeInterface);
88 objectServer.remove_interface(driveInterface);
89}
90
91void EStoraged::formatLuks(const std::vector<uint8_t>& password,
92 Volume::FilesystemType type)
John Wedig2098dab2021-09-14 13:56:28 -070093{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080094 std::string msg = "OpenBMC.0.1.DriveFormat";
95 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080096
John Wedig67a47442022-04-05 17:21:29 -070097 if (type != Volume::FilesystemType::ext4)
John Wedig972c3fa2021-12-29 17:30:41 -080098 {
99 lg2::error("Only ext4 filesystems are supported currently",
100 "REDFISH_MESSAGE_ID", std::string("OpenBMC.0.1.FormatFail"));
101 throw UnsupportedRequest();
102 }
103
John Wedig6218dc52021-12-03 09:36:35 -0800104 CryptHandle cryptHandle(devPath.c_str());
105 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800106 {
107 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
108 std::string("OpenBMC.0.1.FormatFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800109 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800110 }
111
John Wedig6218dc52021-12-03 09:36:35 -0800112 formatLuksDev(cryptHandle.get(), password);
113 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -0800114
115 createFilesystem();
116 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700117}
118
John Wedig67a47442022-04-05 17:21:29 -0700119void EStoraged::erase(Volume::EraseMethod inEraseMethod)
John Wedig2098dab2021-09-14 13:56:28 -0700120{
121 std::cerr << "Erasing encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700122 lg2::info("Starting erase", "REDFISH_MESSAGE_ID",
123 std::string("OpenBMC.0.1.DriveErase"));
124 switch (inEraseMethod)
125 {
John Wedig67a47442022-04-05 17:21:29 -0700126 case Volume::EraseMethod::CryptoErase:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700127 {
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800128 CryptErase myCryptErase(devPath);
129 myCryptErase.doErase();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700130 break;
131 }
John Wedig67a47442022-04-05 17:21:29 -0700132 case Volume::EraseMethod::VerifyGeometry:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700133 {
134 VerifyDriveGeometry myVerifyGeometry(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700135 myVerifyGeometry.geometryOkay();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700136 break;
137 }
John Wedig67a47442022-04-05 17:21:29 -0700138 case Volume::EraseMethod::LogicalOverWrite:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700139 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -0800140 Pattern myErasePattern(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700141 myErasePattern.writePattern();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700142 break;
143 }
John Wedig67a47442022-04-05 17:21:29 -0700144 case Volume::EraseMethod::LogicalVerify:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700145 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -0800146 Pattern myErasePattern(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700147 myErasePattern.verifyPattern();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700148 break;
149 }
John Wedig67a47442022-04-05 17:21:29 -0700150 case Volume::EraseMethod::VendorSanitize:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700151 {
John Edward Broadbent605085a2021-11-05 13:45:45 -0700152 Sanitize mySanitize(devPath);
153 mySanitize.doSanitize();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700154 break;
155 }
John Wedig67a47442022-04-05 17:21:29 -0700156 case Volume::EraseMethod::ZeroOverWrite:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700157 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -0800158 Zero myZero(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700159 myZero.writeZero();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700160 break;
161 }
John Wedig67a47442022-04-05 17:21:29 -0700162 case Volume::EraseMethod::ZeroVerify:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700163 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -0800164 Zero myZero(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700165 myZero.verifyZero();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700166 break;
167 }
John Wedig67a47442022-04-05 17:21:29 -0700168 case Volume::EraseMethod::SecuredLocked:
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700169 {
John Edward Broadbentf59b7292022-02-15 15:07:15 -0800170 if (isLocked())
171 {
172 lock();
173 }
174 // TODO: implement hardware locking
175 // Until that is done, we can lock using eStoraged::lock()
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700176 break;
177 }
178 }
John Wedig2098dab2021-09-14 13:56:28 -0700179}
180
Ed Tanous82897c32022-02-21 14:11:59 -0800181void EStoraged::lock()
John Wedig2098dab2021-09-14 13:56:28 -0700182{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800183 std::string msg = "OpenBMC.0.1.DriveLock";
184 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800185
186 unmountFilesystem();
187 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700188}
189
Ed Tanous82897c32022-02-21 14:11:59 -0800190void EStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700191{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800192 std::string msg = "OpenBMC.0.1.DriveUnlock";
193 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800194
John Wedig6218dc52021-12-03 09:36:35 -0800195 CryptHandle cryptHandle(devPath.c_str());
196 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800197 {
198 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
199 std::string("OpenBMC.0.1.UnlockFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800200 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800201 }
202
John Wedig67a47442022-04-05 17:21:29 -0700203 activateLuksDev(cryptHandle.get(), std::move(password));
John Wedigb810c922021-11-17 16:38:03 -0800204 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700205}
206
John Wedig67a47442022-04-05 17:21:29 -0700207void EStoraged::changePassword(const std::vector<uint8_t>& /*oldPassword*/,
208 const std::vector<uint8_t>& /*newPassword*/)
John Wedig2098dab2021-09-14 13:56:28 -0700209{
210 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700211 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
212 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700213}
214
Ed Tanous82897c32022-02-21 14:11:59 -0800215bool EStoraged::isLocked() const
John Wedigb810c922021-11-17 16:38:03 -0800216{
John Wedig67a47442022-04-05 17:21:29 -0700217 return lockedProperty;
John Wedigb810c922021-11-17 16:38:03 -0800218}
219
Ed Tanous82897c32022-02-21 14:11:59 -0800220std::string_view EStoraged::getMountPoint() const
John Wedigb810c922021-11-17 16:38:03 -0800221{
222 return mountPoint;
223}
224
Ed Tanous82897c32022-02-21 14:11:59 -0800225void EStoraged::formatLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800226 std::vector<uint8_t> password)
227{
228 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
229 std::string("OpenBMC.0.1.FormatLuksDev"));
230
231 /* Generate the volume key. */
232 const std::size_t keySize = 64;
233 std::vector<uint8_t> volumeKey(keySize);
234 if (RAND_bytes(volumeKey.data(), keySize) != 1)
235 {
236 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
237 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800238 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800239 }
240 /* Format the LUKS encrypted device. */
241 int retval =
242 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
243 reinterpret_cast<const char*>(volumeKey.data()),
244 volumeKey.size(), nullptr);
245 if (retval < 0)
246 {
247 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
248 retval, "REDFISH_MESSAGE_ID",
249 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800250 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800251 }
252
253 /* Device is now encrypted. */
254 locked(true);
255
256 /* Set the password. */
257 retval = cryptIface->cryptKeyslotAddByVolumeKey(
258 cd, CRYPT_ANY_SLOT, nullptr, 0,
259 reinterpret_cast<const char*>(password.data()), password.size());
260
261 if (retval < 0)
262 {
263 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
264 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800265 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800266 }
267
268 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
269 "REDFISH_MESSAGE_ID",
270 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
271}
272
Ed Tanous82897c32022-02-21 14:11:59 -0800273void EStoraged::activateLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800274 std::vector<uint8_t> password)
275{
276 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
277 std::string("OpenBMC.0.1.ActivateLuksDev"));
278
279 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
280 if (retval < 0)
281 {
282 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
283 "REDFISH_MESSAGE_ID",
284 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800285 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800286 }
287
288 retval = cryptIface->cryptActivateByPassphrase(
289 cd, containerName.c_str(), CRYPT_ANY_SLOT,
290 reinterpret_cast<const char*>(password.data()), password.size(), 0);
291
292 if (retval < 0)
293 {
294 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
295 "REDFISH_MESSAGE_ID",
296 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800297 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800298 }
299
300 /* Device is now unlocked. */
301 locked(false);
302
303 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
304 "REDFISH_MESSAGE_ID",
305 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
306}
307
Ed Tanous82897c32022-02-21 14:11:59 -0800308void EStoraged::createFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800309{
310 /* Run the command to create the filesystem. */
311 int retval = fsIface->runMkfs(containerName);
Ed Tanous82897c32022-02-21 14:11:59 -0800312 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800313 {
314 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
315 "REDFISH_MESSAGE_ID",
316 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800317 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800318 }
319 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
320 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
321 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
322}
323
Ed Tanous82897c32022-02-21 14:11:59 -0800324void EStoraged::mountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800325{
John Wedigb17f8252022-01-12 14:24:26 -0800326 /*
327 * Create directory for the filesystem, if it's not already present. It
328 * might already exist if, for example, the BMC reboots after creating the
329 * directory.
330 */
331 if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
John Wedigb810c922021-11-17 16:38:03 -0800332 {
John Wedigb17f8252022-01-12 14:24:26 -0800333 bool success =
334 fsIface->createDirectory(std::filesystem::path(mountPoint));
335 if (!success)
336 {
337 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
338 "REDFISH_MESSAGE_ID",
339 std::string("OpenBMC.0.1.MountFilesystemFail"));
340 throw InternalFailure();
341 }
John Wedigb810c922021-11-17 16:38:03 -0800342 }
343
344 /* Run the command to mount the filesystem. */
345 std::string luksContainer("/dev/mapper/" + containerName);
346 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
347 "ext4", 0, nullptr);
Ed Tanous82897c32022-02-21 14:11:59 -0800348 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800349 {
350 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
351 "REDFISH_MESSAGE_ID",
352 std::string("OpenBMC.0.1.MountFilesystemFail"));
353 bool removeSuccess =
354 fsIface->removeDirectory(std::filesystem::path(mountPoint));
355 if (!removeSuccess)
356 {
357 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
358 "REDFISH_MESSAGE_ID",
359 std::string("OpenBMC.0.1.MountFilesystemFail"));
360 }
John Wedig972c3fa2021-12-29 17:30:41 -0800361 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800362 }
363
364 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
365 "REDFISH_MESSAGE_ID",
366 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
367}
368
Ed Tanous82897c32022-02-21 14:11:59 -0800369void EStoraged::unmountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800370{
371 int retval = fsIface->doUnmount(mountPoint.c_str());
Ed Tanous82897c32022-02-21 14:11:59 -0800372 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800373 {
374 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
375 "REDFISH_MESSAGE_ID",
376 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800377 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800378 }
379
380 /* Remove the mount point. */
381 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
382 if (!success)
383 {
384 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
385 "REDFISH_MESSAGE_ID",
386 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800387 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800388 }
389
390 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
391 "REDFISH_MESSAGE_ID",
392 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
393}
394
Ed Tanous82897c32022-02-21 14:11:59 -0800395void EStoraged::deactivateLuksDev()
John Wedigb810c922021-11-17 16:38:03 -0800396{
397 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
398 "REDFISH_MESSAGE_ID",
399 std::string("OpenBMC.0.1.DeactivateLuksDev"));
400
401 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
402 if (retval < 0)
403 {
404 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
405 retval, "REDFISH_MESSAGE_ID",
406 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800407 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800408 }
409
410 /* Device is now locked. */
411 locked(true);
412
413 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
414 "REDFISH_MESSAGE_ID",
415 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
416}
417
John Wedig67a47442022-04-05 17:21:29 -0700418void EStoraged::locked(bool isLocked)
419{
420 lockedProperty = isLocked;
421}
422
John Wedig2098dab2021-09-14 13:56:28 -0700423} // namespace estoraged