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 : /** 146 : * @brief RAII class to hold a temporary key handle that is destroyed on scope exit. 147 : */ 148 : template <class KeyHandleType> 149 : class AutoReleaseSymmetricKey 150 : { 151 : public: 152 46 : explicit AutoReleaseSymmetricKey(SessionKeystore & keystore) : mKeystore(keystore) {} 153 46 : ~AutoReleaseSymmetricKey() { mKeystore.DestroyKey(mKeyHandle); } 154 : 155 92 : KeyHandleType & KeyHandle() { return mKeyHandle; } 156 : 157 : private: 158 : SessionKeystore & mKeystore; 159 : KeyHandleType mKeyHandle; 160 : }; 161 : 162 : } // namespace Crypto 163 : } // namespace chip