@@ -86,6 +86,52 @@ CHIP_ERROR StoreOperationalKey(FabricIndex fabricIndex, PersistentStorageDelegat
86
86
return CHIP_NO_ERROR;
87
87
}
88
88
89
+ CHIP_ERROR ExportStoredOpKey (FabricIndex fabricIndex, PersistentStorageDelegate * storage,
90
+ Crypto::P256SerializedKeypair & serializedOpKey)
91
+ {
92
+ VerifyOrReturnError (storage != nullptr , CHIP_ERROR_INVALID_ARGUMENT);
93
+ VerifyOrReturnError (IsValidFabricIndex (fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
94
+
95
+ // Use a SensitiveDataBuffer to get RAII secret data clearing on scope exit.
96
+ Crypto::SensitiveDataBuffer<OpKeyTLVMaxSize ()> buf;
97
+
98
+ // Load up the operational key structure from storage
99
+ uint16_t size = static_cast <uint16_t >(buf.Capacity ());
100
+ ReturnErrorOnFailure (
101
+ storage->SyncGetKeyValue (DefaultStorageKeyAllocator::FabricOpKey (fabricIndex).KeyName (), buf.Bytes (), size));
102
+
103
+ buf.SetLength (static_cast <size_t >(size));
104
+
105
+ // Read-out the operational key TLV entry.
106
+ TLV::ContiguousBufferTLVReader reader;
107
+ reader.Init (buf.Bytes (), buf.Length ());
108
+
109
+ ReturnErrorOnFailure (reader.Next (TLV::kTLVType_Structure , TLV::AnonymousTag ()));
110
+ TLV::TLVType containerType;
111
+ ReturnErrorOnFailure (reader.EnterContainer (containerType));
112
+
113
+ ReturnErrorOnFailure (reader.Next (kOpKeyVersionTag ));
114
+ uint16_t opKeyVersion;
115
+ ReturnErrorOnFailure (reader.Get (opKeyVersion));
116
+ VerifyOrReturnError (opKeyVersion == kOpKeyVersion , CHIP_ERROR_VERSION_MISMATCH);
117
+
118
+ ReturnErrorOnFailure (reader.Next (kOpKeyDataTag ));
119
+ {
120
+ ByteSpan keyData;
121
+ ReturnErrorOnFailure (reader.GetByteView (keyData));
122
+
123
+ // Unfortunately, we have to copy the data into a P256SerializedKeypair.
124
+ VerifyOrReturnError (keyData.size () <= serializedOpKey.Capacity (), CHIP_ERROR_BUFFER_TOO_SMALL);
125
+
126
+ ReturnErrorOnFailure (reader.ExitContainer (containerType));
127
+
128
+ memcpy (serializedOpKey.Bytes (), keyData.data (), keyData.size ());
129
+ serializedOpKey.SetLength (keyData.size ());
130
+ }
131
+
132
+ return CHIP_NO_ERROR;
133
+ }
134
+
89
135
/* * WARNING: This can leave the operational key on the stack somewhere, since many of the platform
90
136
* APIs use stack buffers and do not sanitize! This implementation is for example purposes
91
137
* only of the API and it is recommended to avoid directly accessing raw private key bits
@@ -106,56 +152,17 @@ CHIP_ERROR SignWithStoredOpKey(FabricIndex fabricIndex, PersistentStorageDelegat
106
152
}
107
153
108
154
// Scope 1: Load up the keypair data from storage
155
+ P256SerializedKeypair serializedOpKey;
156
+ CHIP_ERROR err = ExportStoredOpKey (fabricIndex, storage, serializedOpKey);
157
+ if (CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND == err)
109
158
{
110
- // Use a SensitiveDataBuffer to get RAII secret data clearing on scope exit.
111
- Crypto::SensitiveDataBuffer<OpKeyTLVMaxSize ()> buf;
112
-
113
- // Load up the operational key structure from storage
114
- uint16_t size = static_cast <uint16_t >(buf.Capacity ());
115
- CHIP_ERROR err =
116
- storage->SyncGetKeyValue (DefaultStorageKeyAllocator::FabricOpKey (fabricIndex).KeyName (), buf.Bytes (), size);
117
- if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
118
- {
119
- err = CHIP_ERROR_INVALID_FABRIC_INDEX;
120
- }
121
- ReturnErrorOnFailure (err);
122
- buf.SetLength (static_cast <size_t >(size));
123
-
124
- // Read-out the operational key TLV entry.
125
- TLV::ContiguousBufferTLVReader reader;
126
- reader.Init (buf.Bytes (), buf.Length ());
127
-
128
- ReturnErrorOnFailure (reader.Next (TLV::kTLVType_Structure , TLV::AnonymousTag ()));
129
- TLV::TLVType containerType;
130
- ReturnErrorOnFailure (reader.EnterContainer (containerType));
131
-
132
- ReturnErrorOnFailure (reader.Next (kOpKeyVersionTag ));
133
- uint16_t opKeyVersion;
134
- ReturnErrorOnFailure (reader.Get (opKeyVersion));
135
- VerifyOrReturnError (opKeyVersion == kOpKeyVersion , CHIP_ERROR_VERSION_MISMATCH);
136
-
137
- ReturnErrorOnFailure (reader.Next (kOpKeyDataTag ));
138
- {
139
- ByteSpan keyData;
140
- Crypto::P256SerializedKeypair serializedOpKey;
141
- ReturnErrorOnFailure (reader.GetByteView (keyData));
142
-
143
- // Unfortunately, we have to copy the data into a P256SerializedKeypair.
144
- VerifyOrReturnError (keyData.size () <= serializedOpKey.Capacity (), CHIP_ERROR_BUFFER_TOO_SMALL);
145
-
146
- // Before doing anything with the key, validate format further.
147
- ReturnErrorOnFailure (reader.ExitContainer (containerType));
148
- ReturnErrorOnFailure (reader.VerifyEndOfContainer ());
149
-
150
- memcpy (serializedOpKey.Bytes (), keyData.data (), keyData.size ());
151
- serializedOpKey.SetLength (keyData.size ());
152
-
153
- // Load-up key material
154
- // WARNING: This makes use of the raw key bits
155
- ReturnErrorOnFailure (transientOperationalKeypair->Deserialize (serializedOpKey));
156
- }
159
+ return CHIP_ERROR_INVALID_FABRIC_INDEX;
157
160
}
158
161
162
+ // Load-up key material
163
+ // WARNING: This makes use of the raw key bits
164
+ ReturnErrorOnFailure (transientOperationalKeypair->Deserialize (serializedOpKey));
165
+
159
166
// Scope 2: Sign message with the keypair
160
167
return transientOperationalKeypair->ECDSA_sign_msg (message.data (), message.size (), outSignature);
161
168
}
@@ -251,6 +258,13 @@ CHIP_ERROR PersistentStorageOperationalKeystore::CommitOpKeypairForFabric(Fabric
251
258
return CHIP_NO_ERROR;
252
259
}
253
260
261
+ CHIP_ERROR PersistentStorageOperationalKeystore::ExportOpKeypairForFabric (FabricIndex fabricIndex,
262
+ Crypto::P256SerializedKeypair & outKeypair)
263
+ {
264
+ VerifyOrReturnError (mStorage != nullptr , CHIP_ERROR_INCORRECT_STATE);
265
+ return ExportStoredOpKey (fabricIndex, mStorage , outKeypair);
266
+ }
267
+
254
268
CHIP_ERROR PersistentStorageOperationalKeystore::RemoveOpKeypairForFabric (FabricIndex fabricIndex)
255
269
{
256
270
VerifyOrReturnError (mStorage != nullptr , CHIP_ERROR_INCORRECT_STATE);
@@ -310,4 +324,36 @@ void PersistentStorageOperationalKeystore::ReleaseEphemeralKeypair(Crypto::P256K
310
324
Platform::Delete<Crypto::P256Keypair>(keypair);
311
325
}
312
326
327
+ CHIP_ERROR PersistentStorageOperationalKeystore::MigrateOpKeypairForFabric (FabricIndex fabricIndex,
328
+ OperationalKeystore & operationalKeystore) const
329
+ {
330
+ VerifyOrReturnError (mStorage != nullptr , CHIP_ERROR_INCORRECT_STATE);
331
+ VerifyOrReturnError (IsValidFabricIndex (fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
332
+
333
+ P256SerializedKeypair serializedKeypair;
334
+
335
+ // Do not allow overwriting the existing key and just remove it from the previous Operational Keystore if needed.
336
+ if (!HasOpKeypairForFabric (fabricIndex))
337
+ {
338
+ ReturnErrorOnFailure (operationalKeystore.ExportOpKeypairForFabric (fabricIndex, serializedKeypair));
339
+
340
+ auto operationalKeypair = Platform::MakeUnique<P256Keypair>();
341
+ if (!operationalKeypair)
342
+ {
343
+ return CHIP_ERROR_NO_MEMORY;
344
+ }
345
+
346
+ ReturnErrorOnFailure (operationalKeypair->Deserialize (serializedKeypair));
347
+ ReturnErrorOnFailure (StoreOperationalKey (fabricIndex, mStorage , operationalKeypair.get ()));
348
+
349
+ ReturnErrorOnFailure (operationalKeystore.RemoveOpKeypairForFabric (fabricIndex));
350
+ }
351
+ else if (operationalKeystore.HasOpKeypairForFabric (fabricIndex))
352
+ {
353
+ ReturnErrorOnFailure (operationalKeystore.RemoveOpKeypairForFabric (fabricIndex));
354
+ }
355
+
356
+ return CHIP_NO_ERROR;
357
+ }
358
+
313
359
} // namespace chip
0 commit comments