Line data Source code
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; }
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 46 : explicit AutoReleaseSymmetricKey(SessionKeystore & keystore) : mKeystore(keystore) {}
164 46 : ~AutoReleaseSymmetricKey() { mKeystore.DestroyKey(mKeyHandle); }
165 :
166 92 : KeyHandleType & KeyHandle() { return mKeyHandle; }
167 :
168 : private:
169 : SessionKeystore & mKeystore;
170 : KeyHandleType mKeyHandle;
171 : };
172 :
173 : } // namespace Crypto
174 : } // namespace chip
|