forked from project-chip/connectedhomeip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEfr32PsaOperationalKeystore.h
149 lines (127 loc) · 5.44 KB
/
Efr32PsaOperationalKeystore.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
* Copyright (c) 2022 Project CHIP Authors
* 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.
*/
#pragma once
#include <crypto/OperationalKeystore.h>
#include <lib/core/CHIPConfig.h>
#include <psa/crypto.h>
#include "Efr32OpaqueKeypair.h"
#include <platform/CHIPDeviceLayer.h>
// Set SL_MATTER_MAX_STORED_OP_KEYS to the preferred size of the mapping table
// between fabric IDs and opaque key indices. It can not be less than
// CHIP_CONFIG_MAX_FABRICS + 1 (since there would be too few map elements to
// support all fabrics the application wants to support in addition to an extra
// pending key), but can be larger in case a consistent on-disk size of the map
// is required.
#ifndef SL_MATTER_MAX_STORED_OP_KEYS
#define SL_MATTER_MAX_STORED_OP_KEYS (CHIP_CONFIG_MAX_FABRICS + 1)
#endif
namespace chip {
namespace DeviceLayer {
namespace Internal {
/**
* @brief OperationalKeystore implementation making use of the EFR32 SDK-provided
* storage mechanisms to load/store keypairs.
*
* WARNING: Ensure that any implementation that uses this one as a starting point
* DOES NOT have the raw key material (in usable form) passed up/down to
* direct storage APIs that may make copies on heap/stack without sanitization.
*/
class Efr32PsaOperationalKeystore : public chip::Crypto::OperationalKeystore
{
public:
Efr32PsaOperationalKeystore(){};
virtual ~Efr32PsaOperationalKeystore() override;
// Non-copyable
Efr32PsaOperationalKeystore(Efr32PsaOperationalKeystore const &) = delete;
void operator=(Efr32PsaOperationalKeystore const &) = delete;
/**
* @brief Initialize the Operational Keystore
*/
CHIP_ERROR Init();
bool HasPendingOpKeypair() const override { return (mPendingKeypair != nullptr); }
bool HasOpKeypairForFabric(FabricIndex fabricIndex) const override;
CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override;
CHIP_ERROR ActivateOpKeypairForFabric(FabricIndex fabricIndex, const chip::Crypto::P256PublicKey & nocPublicKey) override;
CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override;
CHIP_ERROR RemoveOpKeypairForFabric(FabricIndex fabricIndex) override;
void RevertPendingKeypair() override;
CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
chip::Crypto::P256ECDSASignature & outSignature) const override;
Crypto::P256Keypair * AllocateEphemeralKeypairForCASE() override;
void ReleaseEphemeralKeypair(chip::Crypto::P256Keypair * keypair) override;
protected:
// The keymap maps PSA Crypto persistent key ID offsets against fabric IDs.
// The keymap is persisted in NVM3, and the keys are stored through the PSA
// API.
FabricIndex * mKeyMap = nullptr;
size_t mKeyMapSize = 0;
// The key cache is to avoid having to reconstruct keys from the storage
// backend all the time (since it is rather slow).
EFR32OpaqueP256Keypair * mCachedKey = nullptr;
// This pending fabric index is `kUndefinedFabricIndex` if there isn't a
// pending keypair override for a given fabric.
FabricIndex mPendingFabricIndex = kUndefinedFabricIndex;
EFR32OpaqueP256Keypair * mPendingKeypair = nullptr;
bool mIsPendingKeypairActive = false;
bool mIsInitialized = false;
private:
void ResetPendingKey(bool keepKeyPairInStorage = false)
{
if (mPendingKeypair != nullptr && !keepKeyPairInStorage)
{
// This removes the PSA Keypair from storage and unloads it
// using the EFR32OpaqueKeypair context.
// We destroy it when the OperationKeyStore process failed.
mPendingKeypair->DestroyKey();
}
Platform::Delete(mPendingKeypair);
mPendingKeypair = nullptr;
mIsPendingKeypairActive = false;
mPendingFabricIndex = kUndefinedFabricIndex;
}
void Deinit()
{
ResetPendingKey();
if (mCachedKey != nullptr)
{
Platform::Delete<EFR32OpaqueP256Keypair>(mCachedKey);
mCachedKey = nullptr;
}
if (mKeyMap != nullptr)
{
Platform::MemoryFree(mKeyMap);
mKeyMap = nullptr;
mKeyMapSize = 0;
}
mIsInitialized = false;
}
/**
* @brief Find the opaque key ID stored in the map for a given
* fabric ID.
*
* @param fabricIndex The fabric index to find the opaque key ID for.
* Can also be kUndefinedFabricIndex to find the first
* unoccupied key ID.
*
* @return a valid key ID on match, or kEFR32OpaqueKeyIdUnknown if no
* match is found.
*/
EFR32OpaqueKeyId FindKeyIdForFabric(FabricIndex fabricIndex) const;
};
} // namespace Internal
} // namespace DeviceLayer
} // namespace chip