Line data Source code
1 : /*
2 : * Copyright (c) 2022 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <crypto/OperationalKeystore.h>
21 : #include <lib/core/CHIPError.h>
22 : #include <lib/core/CHIPPersistentStorageDelegate.h>
23 : #include <lib/core/DataModelTypes.h>
24 : #include <lib/support/CHIPMem.h>
25 : #include <lib/support/CodeUtils.h>
26 :
27 : namespace chip {
28 :
29 : /**
30 : * @brief OperationalKeystore implementation making use of PersistentStorageDelegate
31 : * to load/store keypairs. This is the legacy behavior of `FabricTable` prior
32 : * to refactors to use `OperationalKeystore` and exists as a baseline example
33 : * of how to use the interface.
34 : *
35 : * WARNING: Ensure that any implementation that uses this one as a starting point
36 : * DOES NOT have the raw key material (in usable form) passed up/down to
37 : * direct storage APIs that may make copies on heap/stack without sanitization.
38 : */
39 : class PersistentStorageOperationalKeystore : public Crypto::OperationalKeystore
40 : {
41 : public:
42 : PersistentStorageOperationalKeystore() = default;
43 1 : virtual ~PersistentStorageOperationalKeystore() { Finish(); }
44 :
45 : // Non-copyable
46 : PersistentStorageOperationalKeystore(PersistentStorageOperationalKeystore const &) = delete;
47 : void operator=(PersistentStorageOperationalKeystore const &) = delete;
48 :
49 : /**
50 : * @brief Initialize the Operational Keystore to map to a given storage delegate.
51 : *
52 : * @param storage Pointer to persistent storage delegate to use. Must outlive this instance.
53 : * @retval CHIP_NO_ERROR on success
54 : * @retval CHIP_ERROR_INCORRECT_STATE if already initialized
55 : */
56 : CHIP_ERROR Init(PersistentStorageDelegate * storage)
57 : {
58 : VerifyOrReturnError(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
59 : mPendingFabricIndex = kUndefinedFabricIndex;
60 : mIsExternallyOwnedKeypair = false;
61 : mStorage = storage;
62 : mPendingKeypair = nullptr;
63 : mIsPendingKeypairActive = false;
64 : return CHIP_NO_ERROR;
65 : }
66 :
67 : /**
68 : * @brief Finalize the keystore, so that subsequent operations fail
69 : */
70 1 : void Finish()
71 : {
72 1 : VerifyOrReturn(mStorage != nullptr);
73 :
74 1 : ResetPendingKey();
75 1 : mStorage = nullptr;
76 : }
77 :
78 58 : bool HasPendingOpKeypair() const override { return (mPendingKeypair != nullptr); }
79 :
80 : bool HasOpKeypairForFabric(FabricIndex fabricIndex) const override;
81 : CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override;
82 : CHIP_ERROR ActivateOpKeypairForFabric(FabricIndex fabricIndex, const Crypto::P256PublicKey & nocPublicKey) override;
83 : CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override;
84 : CHIP_ERROR ExportOpKeypairForFabric(FabricIndex fabricIndex, Crypto::P256SerializedKeypair & outKeypair) override;
85 : CHIP_ERROR RemoveOpKeypairForFabric(FabricIndex fabricIndex) override;
86 : void RevertPendingKeypair() override;
87 : CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
88 : Crypto::P256ECDSASignature & outSignature) const override;
89 : Crypto::P256Keypair * AllocateEphemeralKeypairForCASE() override;
90 : void ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair) override;
91 : CHIP_ERROR MigrateOpKeypairForFabric(FabricIndex fabricIndex, OperationalKeystore & operationalKeystore) const override;
92 :
93 : protected:
94 1 : void ResetPendingKey()
95 : {
96 1 : if (!mIsExternallyOwnedKeypair && (mPendingKeypair != nullptr))
97 : {
98 0 : Platform::Delete(mPendingKeypair);
99 : }
100 1 : mPendingKeypair = nullptr;
101 1 : mIsExternallyOwnedKeypair = false;
102 1 : mIsPendingKeypairActive = false;
103 1 : mPendingFabricIndex = kUndefinedFabricIndex;
104 1 : }
105 :
106 : PersistentStorageDelegate * mStorage = nullptr;
107 :
108 : // This pending fabric index is `kUndefinedFabricIndex` if there isn't a pending keypair override for a given fabric.
109 : FabricIndex mPendingFabricIndex = kUndefinedFabricIndex;
110 : Crypto::P256Keypair * mPendingKeypair = nullptr;
111 : bool mIsPendingKeypairActive = false;
112 :
113 : // If overridding NewOpKeypairForFabric method in a subclass, set this to true in
114 : // `NewOpKeypairForFabric` if the mPendingKeypair should not be deleted when no longer in use.
115 : bool mIsExternallyOwnedKeypair = false;
116 : };
117 :
118 : } // namespace chip
|