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