Coverage Report

Created: 2025-08-28 06:31

/src/connectedhomeip/src/crypto/SessionKeystore.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *    Copyright (c) 2023 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/CHIPCryptoPAL.h>
21
#include <lib/support/Span.h>
22
23
namespace chip {
24
namespace Crypto {
25
26
/**
27
 * @brief Interface for deriving session keys and managing their lifetime.
28
 *
29
 * The session keystore interface provides an abstraction that allows the application to store
30
 * session keys in a secure environment. It uses the concept of key handles that isolate the
31
 * application from the actual key material.
32
 *
33
 * @note Refactor has begun to refactor this API into two disctinct APIs : SymmetrycKeyStore & SessionKeyDerivation
34
 *       Work has not been completed so the  SessionKeystore has APIs that shouldn't go together for the time being
35
 *       The SessionKeystore APIs are split into two sections, one for each futur API.
36
 */
37
class SessionKeystore
38
{
39
public:
40
0
    virtual ~SessionKeystore() {}
41
42
    /****************************
43
     * SymmetricKeyStore APIs
44
     *****************************/
45
46
    /**
47
     * @brief Import raw key material and return a key handle for a key that be used to do AES 128 encryption.
48
     *
49
     * @note This method should only be used when using the raw key material in the Matter stack
50
     * cannot be avoided. Ideally, crypto interfaces should allow platforms to perform all the
51
     * cryptographic operations in a secure environment.
52
     *
53
     * If the method returns no error, the application is responsible for destroying the handle
54
     * using the DestroyKey() method when the key is no longer needed.
55
     */
56
    virtual CHIP_ERROR CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Aes128KeyHandle & key) = 0;
57
58
    /**
59
     * @brief Import raw key material and return a key handle for a key that can be used to do 128-bit HMAC.
60
     *
61
     * @note This method should only be used when using the raw key material in the Matter stack
62
     * cannot be avoided. Ideally, crypto interfaces should allow platforms to perform all the
63
     * cryptographic operations in a secure environment.
64
     *
65
     * If the method returns no error, the application is responsible for destroying the handle
66
     * using the DestroyKey() method when the key is no longer needed.
67
     */
68
    virtual CHIP_ERROR CreateKey(const Symmetric128BitsKeyByteArray & keyMaterial, Hmac128KeyHandle & key) = 0;
69
70
    /**
71
     * @brief Import raw key material and return a key handle for an HKDF key.
72
     *
73
     * @note This method should only be used when using the raw key material in the Matter stack
74
     * cannot be avoided. Ideally, crypto interfaces should allow platforms to perform all the
75
     * cryptographic operations in a secure environment.
76
     *
77
     * If the method returns no error, the application is responsible for destroying the handle
78
     * using the DestroyKey() method when the key is no longer needed.
79
     */
80
    virtual CHIP_ERROR CreateKey(const ByteSpan & keyMaterial, HkdfKeyHandle & key) = 0;
81
82
    /**
83
     * @brief Destroy key.
84
     *
85
     * The method can take an uninitialized handle in which case it is a no-op.
86
     * As a result of calling this method, the handle is put in the uninitialized state.
87
     */
88
    virtual void DestroyKey(Symmetric128BitsKeyHandle & key) = 0;
89
90
    /**
91
     * @brief Destroy key.
92
     *
93
     * The method can take an uninitialized handle in which case it is a no-op.
94
     * As a result of calling this method, the handle is put in the uninitialized state.
95
     */
96
    virtual void DestroyKey(HkdfKeyHandle & key) = 0;
97
98
    /****************************
99
     * SessionKeyDerivation APIs
100
     *****************************/
101
102
    /**
103
     * @brief Derive key from a session establishment's `SharedSecret`.
104
     *
105
     * Use `Crypto_KDF` (HKDF) primitive as defined in the Matter specification to derive
106
     * a symmetric (AES) key from the session establishment's `SharedSecret`.
107
     *
108
     * If the method returns no error, the caller is responsible for destroying the symmetric key
109
     * using the DestroyKey() method when the key is no longer needed.
110
     */
111
    virtual CHIP_ERROR DeriveKey(const P256ECDHDerivedSecret & secret, const ByteSpan & salt, const ByteSpan & info,
112
                                 Aes128KeyHandle & key) = 0;
113
114
    /**
115
     * @brief Derive session keys from a session establishment's `SharedSecret`.
116
     *
117
     * Use `Crypto_KDF` (HKDF) primitive as defined in the Matter specification to derive symmetric
118
     * (AES) session keys for both directions, and the attestation challenge from the session
119
     * establishment's `SharedSecret`.
120
     *
121
     * If the method returns no error, the caller is responsible for destroying the symmetric keys
122
     * using the DestroyKey() method when the keys are no longer needed. On failure, the method is
123
     * responsible for releasing all keys that it allocated so far.
124
     */
125
    virtual CHIP_ERROR DeriveSessionKeys(const ByteSpan & secret, const ByteSpan & salt, const ByteSpan & info,
126
                                         Aes128KeyHandle & i2rKey, Aes128KeyHandle & r2iKey,
127
                                         AttestationChallenge & attestationChallenge) = 0;
128
129
    /**
130
     * @brief Derive session keys from a session establishment's `SharedSecret`.
131
     *
132
     * Use Crypto_KDF (HKDF) primitive as defined in the Matter specification to derive symmetric
133
     * (AES) session keys for both directions, and the attestation challenge from the session
134
     * establishment's `SharedSecret`, represented as the key handle.
135
     *
136
     * If the method returns no error, the caller is responsible for destroying the symmetric keys
137
     * using the DestroyKey() method when the keys are no longer needed. On failure, the method is
138
     * responsible for releasing all keys that it allocated so far.
139
     */
140
    virtual CHIP_ERROR DeriveSessionKeys(const HkdfKeyHandle & secretKey, const ByteSpan & salt, const ByteSpan & info,
141
                                         Aes128KeyHandle & i2rKey, Aes128KeyHandle & r2iKey,
142
                                         AttestationChallenge & attestationChallenge) = 0;
143
144
    /**
145
     * @brief Persistently store an ICD key.
146
     *
147
     * If input is already a persistent key handle, the function is a no-op and the original handle is returned.
148
     * If input is a volatile key handle, key is persisted and the handle may be updated.
149
     *
150
     * If the method returns no error, the application is responsible for destroying the handle
151
     * using the DestroyKey() method when the key is no longer needed.
152
     */
153
0
    virtual CHIP_ERROR PersistICDKey(Symmetric128BitsKeyHandle & key) { return CHIP_NO_ERROR; }
Unexecuted instantiation: chip::Crypto::SessionKeystore::PersistICDKey(chip::Crypto::Symmetric128BitsKeyHandle&)
Unexecuted instantiation: chip::Crypto::SessionKeystore::PersistICDKey(chip::Crypto::Symmetric128BitsKeyHandle&)
154
};
155
156
/**
157
 * @brief RAII class to hold a temporary key handle that is destroyed on scope exit.
158
 */
159
template <class KeyHandleType>
160
class AutoReleaseSymmetricKey
161
{
162
public:
163
0
    explicit AutoReleaseSymmetricKey(SessionKeystore & keystore) : mKeystore(keystore) {}
Unexecuted instantiation: chip::Crypto::AutoReleaseSymmetricKey<chip::Crypto::Aes128KeyHandle>::AutoReleaseSymmetricKey(chip::Crypto::SessionKeystore&)
Unexecuted instantiation: chip::Crypto::AutoReleaseSymmetricKey<chip::Crypto::HkdfKeyHandle>::AutoReleaseSymmetricKey(chip::Crypto::SessionKeystore&)
164
0
    ~AutoReleaseSymmetricKey() { mKeystore.DestroyKey(mKeyHandle); }
Unexecuted instantiation: chip::Crypto::AutoReleaseSymmetricKey<chip::Crypto::Aes128KeyHandle>::~AutoReleaseSymmetricKey()
Unexecuted instantiation: chip::Crypto::AutoReleaseSymmetricKey<chip::Crypto::HkdfKeyHandle>::~AutoReleaseSymmetricKey()
165
166
0
    KeyHandleType & KeyHandle() { return mKeyHandle; }
Unexecuted instantiation: chip::Crypto::AutoReleaseSymmetricKey<chip::Crypto::Aes128KeyHandle>::KeyHandle()
Unexecuted instantiation: chip::Crypto::AutoReleaseSymmetricKey<chip::Crypto::HkdfKeyHandle>::KeyHandle()
167
168
private:
169
    SessionKeystore & mKeystore;
170
    KeyHandleType mKeyHandle;
171
};
172
173
} // namespace Crypto
174
} // namespace chip