Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file defines the CHIP Secure Session object that provides
22 : * APIs for encrypting/decryting data using cryptographic keys.
23 : *
24 : */
25 :
26 : #pragma once
27 :
28 : #include <crypto/CHIPCryptoPAL.h>
29 : #include <crypto/SessionKeystore.h>
30 : #include <lib/core/CHIPCore.h>
31 : #include <lib/support/Span.h>
32 : #include <transport/raw/MessageHeader.h>
33 :
34 : namespace chip {
35 :
36 : class DLL_EXPORT CryptoContext
37 : {
38 : public:
39 : static constexpr size_t kPrivacyNonceMicFragmentOffset = 5;
40 : static constexpr size_t kPrivacyNonceMicFragmentLength = 11;
41 : static constexpr size_t kAESCCMNonceLen = 13;
42 : using NonceStorage = std::array<uint8_t, kAESCCMNonceLen>;
43 : using NonceView = FixedSpan<uint8_t, kAESCCMNonceLen>;
44 : using ConstNonceView = FixedSpan<const uint8_t, kAESCCMNonceLen>;
45 :
46 : CryptoContext();
47 : ~CryptoContext();
48 : CryptoContext(CryptoContext &&) = delete;
49 : CryptoContext(const CryptoContext &) = delete;
50 15 : explicit CryptoContext(Crypto::SymmetricKeyContext * context) : mKeyContext(context) {}
51 : CryptoContext & operator=(const CryptoContext &) = delete;
52 : CryptoContext & operator=(CryptoContext &&) = delete;
53 :
54 : /**
55 : * Whether the current node initiated the session, or it is responded to a session request.
56 : */
57 : enum class SessionRole : uint8_t
58 : {
59 : kInitiator, /**< We initiated the session. */
60 : kResponder, /**< We responded to the session request. */
61 : };
62 :
63 : enum class SessionInfoType : uint8_t
64 : {
65 : kSessionEstablishment, /**< A new secure session is established. */
66 : kSessionResumption, /**< An old session is being resumed. */
67 : };
68 :
69 : /**
70 : * @brief
71 : * Derive a shared key. The derived key will be used for encrypting/decrypting
72 : * data exchanged on the secure channel.
73 : *
74 : * @param keystore Session keystore for management of symmetric encryption keys
75 : * @param local_keypair A reference to local ECP keypair
76 : * @param remote_public_key A reference to peer's public key
77 : * @param salt A reference to the initial salt used for deriving the keys
78 : * @param infoType The info buffer to use for deriving session keys
79 : * @param role Role of the new session (initiator or responder)
80 : * @return CHIP_ERROR The result of key derivation
81 : */
82 : CHIP_ERROR InitFromKeyPair(Crypto::SessionKeystore & keystore, const Crypto::P256Keypair & local_keypair,
83 : const Crypto::P256PublicKey & remote_public_key, const ByteSpan & salt, SessionInfoType infoType,
84 : SessionRole role);
85 :
86 : /**
87 : * @brief Derive session keys and the attestation challenge from the shared secret.
88 : *
89 : * @param keystore Session keystore for management of symmetric encryption keys
90 : * @param secret A reference to the shared secret
91 : * @param salt A reference to the initial salt used for deriving the keys
92 : * @param infoType The info buffer to use for deriving session keys
93 : * @param role Role of the new session (initiator or responder)
94 : * @return CHIP_ERROR The result of key derivation
95 : */
96 : CHIP_ERROR InitFromSecret(Crypto::SessionKeystore & keystore, const ByteSpan & secret, const ByteSpan & salt,
97 : SessionInfoType infoType, SessionRole role);
98 :
99 : /**
100 : * @brief Derive session keys and the attestation challenge from the HKDF key.
101 : *
102 : * @param keystore Session keystore for management of symmetric encryption keys
103 : * @param hkdfKey HKDF key handle
104 : * @param salt A reference to the initial salt used for deriving the keys
105 : * @param infoType The info buffer to use for deriving session keys
106 : * @param role Role of the new session (initiator or responder)
107 : * @return CHIP_ERROR The result of key derivation
108 : */
109 : CHIP_ERROR InitFromSecret(Crypto::SessionKeystore & keystore, const Crypto::HkdfKeyHandle & hkdfKey, const ByteSpan & salt,
110 : SessionInfoType infoType, SessionRole role);
111 :
112 : /** @brief Build a Nonce buffer using given parameters for encrypt or decrypt. */
113 : static CHIP_ERROR BuildNonce(NonceView nonce, uint8_t securityFlags, uint32_t messageCounter, NodeId nodeId);
114 :
115 : /** @brief Build a Nonce buffer using given parameters for encrypt or decrypt. */
116 : static CHIP_ERROR BuildPrivacyNonce(NonceView nonce, uint16_t sessionId, const MessageAuthenticationCode & mac);
117 :
118 : /**
119 : * @brief
120 : * Encrypt the input data using keys established in the secure channel
121 : *
122 : * @param input Unencrypted input data
123 : * @param input_length Length of the input data
124 : * @param output Output buffer for encrypted data
125 : * @param nonce Nonce buffer for encrypt
126 : * @param header message header structure. Encryption type will be set on the header.
127 : * @param mac - output the resulting mac
128 : *
129 : * @return CHIP_ERROR The result of encryption
130 : */
131 : CHIP_ERROR Encrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce, PacketHeader & header,
132 : MessageAuthenticationCode & mac) const;
133 :
134 : /**
135 : * @brief
136 : * Decrypt the input data using keys established in the secure channel
137 : *
138 : * @param input Encrypted input data
139 : * @param input_length Length of the input data
140 : * @param output Output buffer for decrypted data
141 : * @param nonce Nonce buffer for decrypt
142 : * @param header message header structure
143 : * @return CHIP_ERROR The result of decryption
144 : * @param mac Input mac
145 : */
146 : CHIP_ERROR Decrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce,
147 : const PacketHeader & header, const MessageAuthenticationCode & mac) const;
148 :
149 : CHIP_ERROR PrivacyEncrypt(const uint8_t * input, size_t input_length, uint8_t * output, PacketHeader & header,
150 : MessageAuthenticationCode & mac) const;
151 :
152 : CHIP_ERROR PrivacyDecrypt(const uint8_t * input, size_t input_length, uint8_t * output, const PacketHeader & header,
153 : const MessageAuthenticationCode & mac) const;
154 :
155 0 : ByteSpan GetAttestationChallenge() const { return mAttestationChallenge.Span(); }
156 :
157 : /**
158 : * @brief
159 : * Memory overhead of encrypting data. The overhead is independent of size of
160 : * the data being encrypted. The extra space is used for storing the common header.
161 : *
162 : * @return number of bytes.
163 : */
164 : size_t EncryptionOverhead();
165 :
166 : bool IsInitiator() const { return mKeyAvailable && mSessionRole == SessionRole::kInitiator; }
167 :
168 0 : bool IsResponder() const { return mKeyAvailable && mSessionRole == SessionRole::kResponder; }
169 :
170 : private:
171 : CHIP_ERROR InitTestMode(Crypto::SessionKeystore & keystore, Crypto::Aes128KeyHandle & i2rKey, Crypto::Aes128KeyHandle & r2iKey);
172 :
173 : SessionRole mSessionRole;
174 :
175 : bool mKeyAvailable;
176 : Crypto::Aes128KeyHandle mEncryptionKey;
177 : Crypto::Aes128KeyHandle mDecryptionKey;
178 : Crypto::AttestationChallenge mAttestationChallenge;
179 : Crypto::SessionKeystore * mKeystore = nullptr;
180 : Crypto::SymmetricKeyContext * mKeyContext = nullptr;
181 :
182 : // Use unencrypted header as additional authenticated data (AAD) during encryption and decryption.
183 : // The encryption operations includes AAD when message authentication tag is generated. This tag
184 : // is used at the time of decryption to integrity check the received data.
185 : static CHIP_ERROR GetAdditionalAuthData(const PacketHeader & header, uint8_t * aad, uint16_t & len);
186 : };
187 :
188 : } // namespace chip
|